Changing system time dynamically win7 - vb.net

Sub change_the_time(ByVal NewDateTime As DateTime)
'
Dim NewDateTime2 As DateTime
'
NewDateTime2 = #5/1/2016 5:52:15 PM# ' try setting the time to this
'
'set the system date and time to this date and time - throw an exception if it can't
Try
TimeOfDay = NewDateTime2
Catch ex As Exception
MessageBox.Show("Could not set time. " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop)
End Try
End Sub
Hi.
New to the site so hopefully I follow the rules :-)
My questions is how do I successfully change the system time? The above code I found on this site (as well as much info on other parts of my project - thank you!) and there are no errors, but it always throws an exception. I run as admin and I've tried changing the UAC and I still can't change the time. I read that I need to have the SE_SYSTEMTIME_NAME privilege set, but I have this set so that all users (ie me) have the right, still nothing. The MS reference here does not provide much insight. I suspect it's an issue with privileges, but i can't seem to see how to set what i need. What do I need to do to allow my application to change the system time to a value?
More info...there is another question along the same lines, but it's c# not Vb and I've tried something similar to that code, which is below. Still
Private Sub change_the_time2(ByRef NewDateTime As DateTime)
Dim d As DateTime
d = #6/10/2011# ' try setting the date to this before using NewDateTime
Dim worked As Boolean
'
Try
worked = setlocaltime(d)
MsgBox(" 1. Did it work " & worked)
Catch ex As Exception
MsgBox(" 2. Did it work " & worked)
End Try
End Sub
<DllImport("kernel32.dll", setLastError:=True)> _
Private Shared Function setlocaltime(ByRef time As System.DateTime) As Boolean
End Function

This is essentially a duplicate of this question as has been mentioned in the comments. But to clarify for VB.NET as oposed to C#, per one of the answers in that question:
On Windows Vista, 7, 8 OS this will require a UAC Prompt in order to
obtain the necessary administrative rights to successfully execute the
SetSystemTime function.
The reason is that calling process needs the
SE_SYSTEMTIME_NAME privilege. The SetSystemTime function is expecting
a SYSTEMTIME struct in coordinated universal time (UTC). It will not
work as desired otherwise.
Depending on where/ how you are getting
your DateTime values, it might be best to play it safe and use
ToUniversalTime() before setting the corresponding values in the
SYSTEMTIME struct.
Code example (modified for VB.NET):
Dim tempDateTime As DateTime = GetDateTimeFromSomeService()
Dim dateTime As DateTime = tempDateTime.ToUniversalTime()
Dim st As SYSTEMTIME
'All of these must be short
st.wYear = dateTime.Year.ToInt16()
st.wMonth = dateTime.Month.ToInt16()
st.wDay = dateTime.Day.ToInt16()
st.wHour = dateTime.Hour.ToInt16()
st.wMinute = dateTime.Minute.ToInt16()
st.wSecond = dateTime.Second.ToInt16()
// invoke the SetSystemTime method now
SetSystemTime(ByRef st)
Yes, you need Administrator privileges.

Related

Drive created by SUBST (Windows 10) Not Reporting Full Path to QueryDosDevice()

EDIT - LOOKS LIKE I FOUND THE PROBLEM
Sorry. Apparently it was all my fault. See my self-written answer below for details.
I'm working on a test for a SUBST-ed drive that's included as a part of a larger method that tests a string to ensure that it's (at least, possibly) a valid path. After a bit of validation, the "encapsulating" method converts the string to a UNC or absolute path, depending on the path that's passed in, to return elsewhere.
A couple of examples:
For drive U:\ mapped to \\SERVERNAME\Share, using the \HKCU\Network\ key in the Windows Registry to find network drive mappings on the local computer, U:\PublicFolder\SomeFile.txt becomes \\SERVERNAME\Share\PublicFolder\SomeFile.txt
Alternately, C:\SomeFolder\SomeFile.txt is left unchanged because (as determined within the method) it's an absolute path to a local, physical drive.
So far, most of this appears to be working well and as expected, but I'm encountering an issue with regards to drives created by the SUBST command in Windows 10 (at least - I haven't run any tests under another OS at this time because I don't have another available to me right now).
To be honest, I don't have much experience with the SUBST command and don't use it very often, so, at first, I was having trouble even getting the drive to show up correctly in Windows. After reading through a discussion on the Microsoft Community page (Windows 10 issue "Subst" command doesn't work), I was finally able to get the drive set up "properly" (don't use an elevated command prompt, BTW), but the code I'm using to test for a SUBST-ed drive - converted to VB.NET from this answer - was still not resolving the full path correctly.
Here's the converted code I'm using (I intend to do some "tweaking" later once I have everything working, but this is the current state):
<DllImport("kernel32.dll", SetLastError:=True)>
Private Shared Function QueryDosDevice(ByVal lpDeviceName As String, ByVal lpTargetPath As System.Text.StringBuilder, ByVal ucchMax As Integer) As UInteger
End Function
Private Shared Function IsSubstPath(ByVal pathToTest As String, <Out> ByRef realPath As String) As Boolean
Dim PathInformation As System.Text.StringBuilder = New System.Text.StringBuilder(260)
Dim DriveLetter As String = Nothing
Dim WinApiResult As UInteger = 0
realPath = Nothing
Try
' Get the drive letter of the path
DriveLetter = IO.Path.GetPathRoot(pathToTest).Replace("\\", "")
Catch ex As ArgumentException
Return False
End Try
WinApiResult = QueryDosDevice(DriveLetter, PathInformation, 260)
If WinApiResult = 0 Then
Dim LastWinError As Integer = Marshal.GetLastWin32Error()
Return False
End If
' If the drive is SUBST'ed, the result will be in the format of "\??\C:\realPath\".
If PathInformation.ToString().StartsWith("\??\") Then
Dim RealRoot As String = PathInformation.ToString().Remove(0, 4)
RealRoot += If(PathInformation.ToString().EndsWith("\"), "", "\")
realPath = IO.Path.Combine(RealRoot, pathToTest.Replace(IO.Path.GetPathRoot(pathToTest), ""))
Return True
End If
realPath = pathToTest
Return False
End Function
Which I call like this for a drive I created using SUBST H: D:\substtest:
Dim TestFile As New IO.FileInfo("H:\0984\CPI.TXT")
Dim SubstPath As String = String.Empty
Dim FullPath As String = String.Empty
If IsSubstPath(FullPath, SubstPath) Then
FullPath = SubstPath
End If
My expectation is that the IsSubstPath() method should return D:\substtest\0984\CPI.TXT via the realPath variable. Executing SUBST (without additional parameters) correctly showed the mapping in the command prompt (H:\: => D:\substtest). Checking the TestFile object while debugging shows that it's Exists() property returns True, so the file system does, apparently, know that it's there.
At this point, every time I execute the code, the QueryDosDevice() method call returns a value of 0, although I get varying results from the Marshal.GetLastWin32Error() call as I continue to try to get this working.
My first attempt after getting the SUBST-ed drive "properly" set up on my machine resulted in the Marshal.GetLastWin32Error() returning error code 1008 - ERROR_NO_TOKEN ("An attempt was made to reference a token that does not exist").
Further reading in the linked MS community thread indicated that running SUBST twice - once in a normal command prompt, and again in an elevated command prompt - should make the drive available to either a regular logged on user as well as any elevated user action. I re-ran SUBST in an elevated command prompt and tried again using the same testing code as above. This time, Marshal.GetLastWin32Error() returned error code 6 - ERROR_INVALID_HANDLE ("The handle is invalid.").
Thinking this particular operation might be dependent on the file/path actually existing on the system (as opposed to the .NET IO.FileInfo or IO.DirectoryInfo objects), I manually created the specific subfolder and file to represent what I was testing for in my code (H:\0984\CPI.TXT) and tried it once more (again, using the same code as above):
Once again, the QueryDosDevice() failed to correctly parse the real path (returned 0), but this time the Marshal.GetLastWin32Error() method returned a value of 0 - ERROR_SUCCESS ("The operation completed successfully."). Thinking that, perhaps there was some "flaw" in the code that might unintentionally be skipping a step or something, I checked the PathInformation variable - the Text.StringBuilder object that holds the results of the QueryDosDevice() - in break mode but, alas it's also empty.
NOTE: I also tried using a directory instead of a file, but H:\0984\ resulted in a Marshal.GetLastWin32Error() return value of 0 while H:\0984 resulted in a value of 6. Based on the previous testing, this all makes sense but it nonetheless results in an empty PathInformation variable (failure).
Reading all around the Interwebz, it seems many people are experiencing a variety of issues with SUBST-ed drives under Windows 10, so I'm left wondering at this point if that's the reason for these unexpected results. Has anyone else encountered these issues and, if so, have you been able to resolve them in code?
In case it matters (as I suppose it certainly might), here are some additional details:
I'm using Visual Studio 2017 CE and my project is compiling under .NET Framework 4.7.2
The physical drive to which I'm creating the SUBST path is a RAID 1 pair of drives formatted with NTFS and has plenty of space (178 GB).
NOTE: I have also tried creating a SUBST-ed path to my OS drive (C:\) for the testing, but this gets the same results as above.
If I've left anything out, or if you require further clarification, please let me know in the comments and I'll update the question as needed.
DOUBLE/TRIPLE/QUADRUPLE CHECK CONVERTED CODE
Looks like it all comes down to a single line of code to which I wasn't paying close enough attention (line 14 in the code block above):
DriveLetter = IO.Path.GetPathRoot(PathToTest).Replace("\\", "")
The problem here is that the Path.GetPathRoot() method returns the drive letter in the format H:\ - there's only one backslash (\), so the .Replace() method didn't find anything to replace and was passing an "invalid" parameter value (H:\ instead of H:). The QueryDosDevice() method will apparently fail if the trailing backslash is there, so I made a quick code edit:
DriveLetter = IO.Path.GetPathRoot(PathToTest).Replace("\", "") ' <--Replace ANY/ALL backslashes
I again tested with my SUBST H: D:\substtest drive with an existing file/directory structure as above. This time, the QueryDosDevice() method returned a value of 19 and correctly parsed the real path as D:\substtest\0984\CPI.TXT.
Then, I deleted the subfolder/file I had created for testing and tried again. Again, it correctly returned the real path as D:\substtest\0984\CPI.TXT. So, apparently it all comes down to me overlooking a "typo" introduced during my conversion of the code from C# to VB.NET. My apologies. The full, corrected version of the converted code
<DllImport("kernel32.dll", SetLastError:=True)>
Private Shared Function QueryDosDevice(ByVal lpDeviceName As String, ByVal lpTargetPath As System.Text.StringBuilder, ByVal ucchMax As Integer) As UInteger
End Function
Private Shared Function IsSubstPath(ByVal pathToTest As String, <Out> ByRef realPath As String) As Boolean
Dim PathInformation As System.Text.StringBuilder = New System.Text.StringBuilder(260)
Dim DriveLetter As String = Nothing
Dim WinApiResult As UInteger = 0
realPath = Nothing
Try
' Get the drive letter of the path without the trailing backslash
DriveLetter = IO.Path.GetPathRoot(pathToTest).Replace("\", "")
Catch ex As ArgumentException
Return False
End Try
WinApiResult = QueryDosDevice(DriveLetter, PathInformation, 260)
If WinApiResult = 0 Then
Dim LastWinError As Integer = Marshal.GetLastWin32Error()
Return False
End If
' If the drive is SUBST'ed, the result will be in the format of "\??\C:\realPath\".
If PathInformation.ToString().StartsWith("\??\") Then
Dim RealRoot As String = PathInformation.ToString().Remove(0, 4)
RealRoot += If(PathInformation.ToString().EndsWith("\"), "", "\")
realPath = IO.Path.Combine(RealRoot, pathToTest.Replace(IO.Path.GetPathRoot(pathToTest), ""))
Return True
End If
realPath = pathToTest
Return False
End Function
As I said in the question, I intend to do some "tweaking" of this method, but this does work (now).

VB.Net and handling dates within Grid Controls - better way?

While I have my app running, I question the methodology, and wondering if there’s a “better way”…
Overall design is to allow editing 200-300 records from a gridview (phase1) using VB.Net. The database itself is on SQL Server. There are a number of columns a user will enter into an “application”, and there are several columns that will be edited/maintained by “office users”, if you will. There are several dates involved in this ongoing maintenance, and that’s where the first of my questions revolves.
I have found “solutions” on the internet that got the code working, but am questioning them…
Problem #1 I ran into – dates are NULL in the database, and in trying to read them in using a SqlDataReader led to errors (cannot assign NULL to a Date object). Ok, that led into using a ternary operator to use “IsDBNull”, and either assign the value read from the DB, or to assign DateTime.MinValue. Problem “solved”…
Problem #2 – using the above method now shows dates that are the minimum VB date value – showing actual dates in the fields the user is to edit – definitely not “user friendly”, nor what I want. The only solution to this issue was:
Convert dates from Date or DateTime objects into String objects. This would then allow me to be able to assign an empty string to the gridview in the case where the date was originally NULL in the DB, which had to be transformed into DateTime.MinValue (which could be tested), and then another ternary operator to assign either “ToString” conversion, or an empty string to the gridview field.
Ok – editing is now accomplished. I added some “ScriptManager.RegisterStartupScript” commands to allow testing the validity of the dates the user enters – all is well.
Problem #3 (or 4) – I now need to update the database with the data the user entered – PRESERVING THE EMPTY DATE STRINGS – and update the database (using parameters…) with NULLs back in those date columns. However, again – the date is a string, and is empty, so I had to assign to a “MinValue”, first, then another ternary operator to test each date against “MinValue”, and either assign the date, or a DBNull.Value…
Yes, I guess I could have come up with a number of different update strings (including dates in some, excluding in others), depending on whether or not a string/date was empty or not... But that will only lead to future bugs, so, I guess I’ll be keeping a series of ternary operators.
So, the code for beginning the edit process looks something like:
While sdr.Read
Dim _date1 As Date = If(IsDBNull(sdr("date1")), DateTime.MinValue, sdr("date1"))
.
.
.
‘ Now add them to a List of my Class:
appsList.Add(New AppClass(… _
If(_date1 = DateTime.MinValue, " ", _date1.ToString("MM/dd/yyyy")), _
… )
Now to get the data back from the gridview to update the database:
Dim _date1 As Date
' see if we can convert the various dates...
Try
' see if empty…
If ((CType((row.Cells(19).Controls(0)), TextBox)).Text).Length < 2 Then
_date1 = DateTime.MinValue
Else
_date1 = DateTime.Parse((CType((row.Cells(19).Controls(0)), TextBox)).Text)
End If
Catch ex As Exception
ErrFlag = True
ScriptManager.RegisterStartupScript(Me, Page.GetType, "Script", "alert(‘Date1 Date is not valid - enter as MM/DD/YYYY');", True)
End Try
.
.
.
Dim sql As String = "UPDATE [foo_bar].[dbo].[bar_foo] set date1=#Date1, …….)
cmd.Parameters.AddWithValue("#Date1", If(_date1 = DateTime.MinValue, DBNull.Value, _date1))
Honestly, all this conversion back and forth seems like it’s going to lead to bugs or errors at some point.
So – is this the “best” method for handling this? There isn’t a cleaner way?
If your using winforms then you can handle the Format and parse of the databindings. I haven't tried it on a Gridviewtextbox but worst case you can use a custom cell template and a textbox with format and parse handlers. The code would be something like this:
mybinding = New Binding("text", DataSet1, "table1.datefield")
Me.DataGridTextBoxColumn1.TextBox.DataBindings.Add(mybinding)
AddHandler mybinding.Parse, AddressOf StringToDateTime
AddHandler mybinding.Format, AddressOf formatdate
Private Sub StringToDateTime(ByVal sender As Object, ByVal cevent As ConvertEventArgs)
If cevent.Value.GetType().Equals(GetType(String)) And _
cevent.DesiredType Is GetType(DateTime) Then
If cevent.Value <> "" Then
' Make sure matches format in format funtion
cevent.Value = DateTime.Parse(String.Format(cevent.Value, "MMM d, yy"))
Else
cevent.Value = DBNull.Value
End If
'cevent.Value = DateTime.Parse(String.Format(cevent.Value, "MMM d yyyy")
End If
End Sub
Public Sub formatdate(ByVal sender As Object, ByVal e As ConvertEventArgs)
If e.Value.GetType().Equals(GetType(DateTime)) And e.DesiredType Is GetType(String) Then
' Hard-coded or user-specified
' Make sure matches format in parse funtion
e.Value = Format(e.Value, "d")
End If
End Sub

having couple of sub under one command button VBA

I am designing a user interface that is supposed to do everything by just clicking on the " Run" button.
It has to do lots of calculation and is getting heavier and heavier. Is there any way that I can define sub under
"Private Sub Run_Click()" ?
I want to make the program faster to be run. I have an error of " runtime error 6 overflow vba"
Also this is the code that includes a heavy loop:
Dim NewDate As Long
Dim i As Long
For i = 3 To End_date_Calendar
NewDate = DateAdd("d", i - 3, strDate)
Worksheets("Calcul").Cells(i, "AB").Value = NewDate
Next i
Where is End_date_Calendar set?
. . .
I don't believe there there is enough code or details to determine what may be overloading. What does the debug watch expressions say at the error point?

Delete registry after year Vb net

How can I make my licence works only one year? When I activated my program I add registry with current date. On each run I check if the registry exist. If registry exists I can use my application otherwise it prompt me to activate it .
I want to make that my licence works only one year.
I tried with
Public Sub Licence_Check()
Dim licenca As Date
Dim days As Integer
licenca = CDate(My.Computer.Registry.GetValue("HKEY_CURRENT_USER\tFull", "tFull", Nothing))
days = CInt(365 - (DateDiff(DateInterval.Day, licenca, Now)))
If days <= 0 Then
My.Computer.Registry.CurrentUser.DeleteValue("tFull")
pbInfo.Value = pbInfo.Maximum
gpbInfo.Text = "One year Licence OVER"
RbContinue.Enabled = False
End If
End Sub
I have already warned you about the weakness of this approach, but this is how you could write the above License_Check
Public Sub Licence_Check()
Dim licenca As Date
Using tempKey = My.Computer.Registry.CurrentUser.OpenSubKey("Software\YourAppNameHere", true)
licenca = CDate(tempKey.GetValue("InstallDate", Nothing))
Dim limit = licenca.AddYears(1)
if limit < DateTime.Today
tempKey.DeleteValue("InstallDate")
Console.WriteLine ("One year Licence OVER")
End If
End Using
End Sub
Notice that you should store your application info in a subkey of the SOFTWARE subkey and not directly under the root HKEY_CURRENT_USER. Then you need to open the appropriate subkey asking for the write permissions and finally read the value desidered.
To check the dates just add 1 year to the value read and do the check against Today.
To delete you should use the DeleteValue method of the opened subkey.
Also I suppose that this is not a check that should be applied on a user by user base. Instead it is a check that could be applied to the whole application. In this case you should use the predefined My.Computer.Registry.LocalMachine registry key.

Dynamic programming in VB

We develop applications for SAP using their SDK. SAP provides a SDK for changing and handling events occuring in the user interface.
For example, with this SDK we can catch a click on a button and do something on the click. This programming can be done either VB or C#.
This can also be used to create new fields on the pre-existing form. We have developed a specific application which allows users to store the definition required for new field in a database table and the fields are created at the run time.
So far, this is good. What we require now is that the user should be able to store the validation code for the field in the database and the same should be executed on the run time.
Following is an example of such an event:
Private Sub SBO_Application_ItemEvent(ByVal FormUID As String, ByRef pVal As SAPbouiCOM.ItemEvent, ByRef BubbleEvent As Boolean) Handles SBO_Application.ItemEvent
Dim oForm As SAPbouiCOM.Form
If pVal.FormTypeEx = "ACC_QPLAN" Then
If pVal.EventType = SAPbouiCOM.BoEventTypes.et_LOST_FOCUS And pVal.BeforeAction = False Then
oProdRec.ItemPressEvent(pVal)
End If
End If
End Sub
Public Sub ItemPressEvent(ByRef pVal As SAPbouiCOM.ItemEvent)
Dim oForm As SAPbouiCOM.Form
oForm = oSuyash.SBO_Application.Forms.GetForm(pVal.FormTypeEx, pVal.FormTypeCount)
If pVal.EventType = SAPbouiCOM.BoEventTypes.et_LOST_FOCUS And pVal.BeforeAction = False Then
If pVal.ItemUID = "AC_TXT5" Then
Dim CardCode, ItemCode As String
ItemCode = oForm.Items.Item("AC_TXT2").Specific.Value
CardCode = oForm.Items.Item("AC_TXT0").Specific.Value
UpdateQty(oForm, CardCode, ItemCode)
End If
End If
End Sub
So, what we need in this case is to store the code given in the ItemPressEvent in a database, and execute this in runtime.
I know this is not straight forward thing. But I presume there must be some ways of getting these kind of things done.
The SDK is made up of COM components.
Thanks & Regards,
Rahul Jain
I've not done this myself, but I think you're going to have to actually use the Systems.Runtime.CompilerServices functions to dynamically compile an assembly and then link it in. Another solution if you are using SQL Server might be to take advantage of the fact that you can write C# or VB.NET code in stored procedures. That might be a way.
Dim sqlstring1 As String = "Blah Blah Blah SQL here"
Dim Rs SAPbobsCOM.Recordset
Rs = GetDIConnection.GetBusinessObject(SAPbobsCOM.BoObjectTypes.BoRecordset)
rs.doquery(SqlString1)
You can create the code dynamically and compile it..
Have some simple interfaces to call the validation code and in all your dynamic code, implement the interface(s). This way, you can load assembly dynamically and get the class as an interface and use that interface directly..