Hello question answering person of awesomeness!
I am trying to find a way to accurately verify if a Windows 7 machine is currently using an active license and activated. I believe I can initiate a 'cmd.exe' command to run a cscript (slmgr) and parse that information but that seems like an inefficient method.
I have came across an unmanaged windows API called SLGetGenuineInformation ( http://msdn.microsoft.com/en-us/library/windows/desktop/bb648650%28v=vs.85%29.aspx ) however I am not familiar with how to call this in VB.NET or what the variable types should be. I believe VB6 came with some sort of APIViewer that Visual STudio 2010 does not seem to contain.
All relevant Google searches turn up as unrelevant results.
Any suggestions, advice, or guidance on how to proceed or accomplish this goal?
Check this sample vb.net console app, that uses the SLIsGenuineLocal function.
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.InteropServices
Imports SLID = System.Guid
Module Module1
Public Enum SL_GENUINE_STATE
SL_GEN_STATE_IS_GENUINE = 0
SL_GEN_STATE_INVALID_LICENSE = 1
SL_GEN_STATE_TAMPERED = 2
SL_GEN_STATE_LAST = 3
End Enum
<DllImportAttribute("Slwga.dll", EntryPoint:="SLIsGenuineLocal", CharSet:=CharSet.None, ExactSpelling:=False, SetLastError:=False, PreserveSig:=True, CallingConvention:=CallingConvention.Winapi, _
BestFitMapping:=False, ThrowOnUnmappableChar:=False)> _
<PreserveSigAttribute()> _
Friend Function SLIsGenuineLocal(ByRef slid As SLID, <[In](), Out()> ByRef genuineState As SL_GENUINE_STATE, ByVal val3 As IntPtr) As UInteger
End Function
Public Function IsGenuineWindows() As Boolean
Dim _IsGenuineWindows As Boolean = False
Dim ApplicationID As New Guid("55c92734-d682-4d71-983e-d6ec3f16059f")
'Application ID GUID http://technet.microsoft.com/en-us/library/dd772270.aspx
Dim windowsSlid As SLID = CType(ApplicationID, Guid)
Try
Dim genuineState As SL_GENUINE_STATE = SL_GENUINE_STATE.SL_GEN_STATE_LAST
Dim ResultInt As UInteger = SLIsGenuineLocal(windowsSlid, genuineState, IntPtr.Zero)
If ResultInt = 0 Then
_IsGenuineWindows = (genuineState = SL_GENUINE_STATE.SL_GEN_STATE_IS_GENUINE)
Else
Console.WriteLine("Error getting information {0}", ResultInt.ToString())
End If
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Return _IsGenuineWindows
End Function
Sub Main()
If Environment.OSVersion.Version.Major >= 6 Then
'Version 6 can be Windows Vista, Windows Server 2008, or Windows 7
If IsGenuineWindows() Then
Console.WriteLine("Original Windows")
Else
Console.WriteLine("Not Original Windows")
End If
Else
Console.WriteLine("OS Not supoprted")
End If
Console.ReadLine()
End Sub
End Module
If it helps this is VC++ example
#include <slpublic.h>
#pragma comment(lib,"Slwga.lib")
bool IsWindowsGenuine()
{
GUID uid;
RPC_WSTR rpc=(RPC_WSTR)_T("55c92734-d682-4d71-983e-d6ec3f16059f");
UuidFromString(rpc,&uid);
SL_GENUINE_STATE state;
SLIsGenuineLocal(&uid,&state,NULL);
if(state==SL_GENUINE_STATE::SL_GEN_STATE_IS_GENUINE)
return true;
return false;
}
Here is VB Sript that does it:
trComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colWPA = objWMIService.ExecQuery _
("Select * from Win32_WindowsProductActivation")
For Each objWPA in colWPA
Wscript.Echo "Activation Required: " & objWPA.ActivationRequired
Wscript.Echo "Description: " & objWPA.Description
Wscript.Echo "Product ID: " & objWPA.ProductID
Wscript.Echo "Remaining Evaluation Period: " & _
objWPA.RemainingEvaluationPeriod
Wscript.Echo "Remaining Grace Period: " & objWPA.RemainingGracePeriod
Wscript.Echo "Server Name: " & objWPA.ServerName
Next
Source: How to check if a Windows version is Genuine or not?
If you want to read it directly from OS register you can read upon using VB to work whit register here: http://www.codeproject.com/KB/vb/registry_with_vb.aspx
Related
I am trying to create a registry key and subkey for enabling IE 11 enterprise mode for all users on a machine. This is what I am using for my VBScript currently and it is failing horribly (does not add the key). I could use some assistance in getting this corrected.
Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set ObjRegistry = _
GetObject("winmgmts:{impersonationLevel = impersonate}! \\" & _
strComputer & "\root\default:StdRegProv")
strPath = strKeyPath & "\" & strSubPath
strKeyPath = "Software\Policies\Microsoft"
strSubPath = "Internet Explorer\Main\EnterpriseMode"
strName = "Enabled"
ObjRegistry.CreateKey (HKEY_LOCAL_MACHINE, strPath)
ObjRegistry.SetStringValue HKEY_LOCAL_MACHINE, strPath, strName, strValue
MsgBox "Successfully enabled Internet Explorer Enterprise Mode."
End Function
There are several issues with your code, aside from the fact that you posted an incomplete code sample.
"winmgmts:{impersonationLevel = impersonate}! \\" & strComputer & "\root\default:StdRegProv"
The WMI moniker contains a spurious space between security settings and path (...! \\...). Remove it.
As a side note, it's pointless to use a variable for the hostname if that hostname never changes.
strPath = strKeyPath & "\" & strSubPath
You define strPath before you define the variables you build the path from. Also, your path components are defined as string literals, so you could drop the concatenation and the additional variables and simply define strPath as a string literal.
ObjRegistry.CreateKey (HKEY_LOCAL_MACHINE, strPath)
You must not put argument lists in parentheses unless you're calling the function/method/procedure in a subexpression context. See here for more details. However, you may want to check the return value of your method calls to see if they were successful.
And FTR, hungarian notation is pointless code bloat. Don't use it.
Modified code:
Function SetEnterpriseMode(value)
Const HKLM = &h80000002
Set reg = GetObject("winmgmts:{impersonationLevel=impersonate}!//./root/default:StdRegProv")
path = "Software\Policies\Microsoft\Internet Explorer\Main\EnterpriseMode"
name = "Enabled"
rc = reg.CreateKey(HKLM, path)
If rc <> 0 Then
MsgBox "Cannot create key (" & rc & ")."
Exit Function
End If
rc = reg.SetStringValue(HKLM, path, name, value)
If rc = 0 Then
MsgBox "Successfully enabled Internet Explorer Enterprise Mode."
Else
MsgBox "Cannot set value (" & rc & ")."
End If
End Function
I need a function that returns a String, using the hardware serial numbers and mixing them together to obtain a single serial number.
I searched try a function like this but I can not find anything similar, this function need to identify a pc with a licensing system.
I only need a same value per computer.
This may not be exactly what you want but if i understand your question correctly, play around with the below code (Don't use the code below with Strict On) not the best of ideas but it works...
Private Function SystemSerialNumber() As String
' Get the Windows Management Instrumentation object.
Dim wmi As Object = GetObject("WinMgmts:")
' Get the "base boards" (mother boards).
Dim serial_numbers As String = ""
Dim mother_boards As Object = _
wmi.InstancesOf("Win32_BaseBoard")
For Each board As Object In mother_boards
serial_numbers &= ", " & board.SerialNumber
Next board
If serial_numbers.Length > 0 Then serial_numbers = _
serial_numbers.Substring(2)
Return serial_numbers
End Function
Private Function CpuId() As String
Dim computer As String = "."
Dim wmi As Object = GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & _
computer & "\root\cimv2")
Dim processors As Object = wmi.ExecQuery("Select * from " & _
"Win32_Processor")
Dim cpu_ids As String = ""
For Each cpu As Object In processors
cpu_ids = cpu_ids & ", " & cpu.ProcessorId
Next cpu
If cpu_ids.Length > 0 Then cpu_ids = _
cpu_ids.Substring(2)
Return cpu_ids
End Function
Source:
http://www.vb-helper.com/howto_net_get_cpu_serial_number_id.html
I am trying to update an ancient VB6 project to enable communication with a remote OPC Server. I have installed the Siemens toolkit but I am unable to find any useful documentation on how to use it with VB6. (Works with C#)
The application is very simple. I just need to connect to the remote server and write/read single addresses.
I found the DatCon OCX control which I assume handles the communication but all the ServerName values I tried to enter by hand did not work.
Can anyone help?
Add a reference to the DLL or OCX (the seimens toolkit) to your VB6 project and then use the object browser to browse around the exposed objects. You can often times figure out what you need just be doing that.
The C# docs should also provide a wealth of info. If the library is a COM library, you'll use it essentially the same way from VB6.
Since posting, I did make some progress. The following example helped me to get going.
http://support.automation.siemens.com/WW/llisapi.dll?func=cslib.csinfo&objId=25229521&load=treecontent&lang=en&siteid=cseus&aktprim=0&objaction=csview&extranet=standard&viewreg=WW
Here is my current code. It's not much - just makes contact with the server and tries to write a value. I didn't get any further. I started getting COM errors and assumed the installation was bad (I had had problems installing) so I decided to reinstall. It didn't work. Installation was impossible. Waiting for an upgrade from Siemens.
'
' OPC Communication
'
' Paul Ramsden 24.11.2011
'
'
Option Explicit
Option Base 1
Public MyOpcServer As OPCServer
Public ServerHandle As Variant
Private ServerName As String
Private ServerNode As String
Private TestGroup As OPCGroup
Private MyOpcItem As OPCItem
Private IsInitialised As Boolean
Public Sub InitialiseOPC()
On Error GoTo ProcError
IsInitialised = False
Set MyOpcServer = New OPCServer
ServerNode = "xyz.abc.10.101"
ServerName = "OPC.SimaticNET.1"
Dim LocalServers
LocalServers = MyOpcServer.GetOPCServers(ServerNode)
Dim tmp
ServerHandle = ""
For Each tmp In LocalServers
If CStr(tmp) = ServerName Then
Call MyOpcServer.Connect(tmp)
MsgBox MyOpcServer.ServerNode & vbCr & MyOpcServer.ServerName & vbCr & MyOpcServer.ServerState
ServerHandle = tmp
Set TestGroup = MyOpcServer.OPCGroups.Add("TestGroup")
Exit For
End If
Next
If ServerHandle = "" Then
MsgBox "Could not find server " & ServerName & " on " & ServerNode
Else
IsInitialised = True
End If
ProcExit:
Exit Sub
ProcError:
MsgBox Err.Description
Resume ProcExit
End Sub
Private Sub ClearGroup()
Dim handles() As Long
Dim errors() As Long
Call TestGroup.OPCItems.Remove(TestGroup.OPCItems.Count, handles, errors)
End Sub
Public Sub WriteOPC(address As String, value As String)
On Error GoTo ProcError
Call ClearGroup
Set MyOpcItem = TestGroup.OPCItems.AddItem(address, 2011)
MyOpcItem.Write (value)
Exit Sub
ProcError:
MsgBox "Write error! " & Err.Description
End Sub
Public Function ReadOPC(address As String) As String
On Error GoTo ProcError
Call ClearGroup
Set MyOpcItem = TestGroup.OPCItems.AddItem(address, 2011)
Dim value As String
ReadOPC = MyOpcItem.Read
ProcError:
MsgBox "Read error! " & Err.Description
End Function
Public Sub TestOPC()
InitialiseOPC
WriteOPC "SIMATIC 300(1).CPU 315-2 DP.Q0_0TestAusgang1", "1"
End Sub
I need to write a little application in VB6 to run instances of another VB6 application and keep an eye on the running processes, but I don't have any idea how to get process information in VB6. I can see some of what I need with the tasklist utility but I don't really know how create processes (specifying the process or application name if possible) and fetching information about processes from the operating system.
This application is to run on a Windows XP machine.
Does anyone know of a get-you-started tutorial or helpful web page for this sort of thing?
There are numerous Windows API functions you can use to do this. I'd start with looking at EnumProcesses (VB6 example and declaration here) which can be used to gather information about all running processes. You can also use OpenProcess
to start interrogating Windows about a particular process (another VB6 example).
There is also a fairly nice example on MSDN.
And of course, there is CreateProcess (AllApi link) or ShellExecute (AllApi) for spawning processes - the former gives you more control over the creation of the process, while the latter is a much simpler call.
There was another question posted about this a while back with some example code.
Another possible approach would be to use WMI (some useful snippets to adapt).
Finally, here are some tutorials that show you how to do it (I'd recommend trying it yourself first though :):
Getting Process Information using PSAPI
Another EnumProcesses/OpenProcess implementation
WMI-based demonstration
Here are some related questions although you probably already saw them when you searched this site before posting:
Monitoring processes to see if they've crashed in vb6
How can I execute a .bat file but wait until its done running before moving on?
How To Enumerate Processes From VB 6 on Win 2003?
Since you say the other application is ** also VB6**, it would be easier to make the other application into an ActiveX exe. Then you can get references to objects in the other application direct from your first application. COM solves it all for you.
Here's Microsoft's tutorial on the subject - you can download the code too.
Or here's another answer where I've written about this
You don't need to go spelunking for processes just to get a handle to child processes that you spawn. The VB6 Shell() function returns a Process ID you can use to call OpenProcess with. CreateProcess gives you the handle directly.
Ok, here is a super-stripped-down example of a program in VB6 to spawn and monitor programs. The example is coded to start and repeatedly restart 3 copies of the command shell (trivial sample child program). It is also written to kill any running children when it is terminated, and there are better alternatives to use in most cases. See A Safer Alternative to TerminateProcess().
This demo also reports back the exit code of each process that quits. You could enter exit 1234 or somesuch to see this in action.
To create the demo open a new VB6 Project with a Form. Add a multiline TextBox Text1 and a Timer Timer1 (which is used to poll the children for completion). Paste this code into the Form:
Option Explicit
Private Const SYNCHRONIZE = &H100000
Private Const PROCESS_QUERY_INFORMATION = &H400&
Private Const PROCESS_TERMINATE = &H1&
Private Const WAIT_OBJECT_0 = 0
Private Const INVALID_HANDLE = -1
Private Const DEAD_HANDLE = -2
Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" ( _
ByVal hProcess As Long, _
ByRef lpExitCode As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" ( _
ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" ( _
ByVal hProcess As Long, _
ByVal uExitCode As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" ( _
ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Tasks() As String
Private Handles() As Long
Private Sub Form_Load()
Dim I As Integer
'We'll run 3 copies of the command shell as an example.
ReDim Tasks(2)
ReDim Handles(2)
For I = 0 To 2
Tasks(I) = Environ$("COMSPEC") & " /k ""#ECHO I am #" & CStr(I) & """"
Handles(I) = INVALID_HANDLE
Next
Timer1.Interval = 100
Timer1.Enabled = True
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim I As Integer
Timer1.Enabled = False
DoEvents
For I = 0 To UBound(Tasks)
If Handles(I) <> INVALID_HANDLE And Handles(I) <> DEAD_HANDLE Then
TerminateProcess Handles(I), 666
CloseHandle Handles(I)
Handles(I) = DEAD_HANDLE
End If
Next
End Sub
Private Sub Timer1_Timer()
Dim I As Integer
Dim ExitCode As Long
Dim Pid As Long
Timer1.Enabled = False
For I = 0 To UBound(Tasks)
If Handles(I) <> INVALID_HANDLE Then
If WaitForSingleObject(Handles(I), 0) = WAIT_OBJECT_0 Then
If GetExitCodeProcess(Handles(I), ExitCode) <> 0 Then
Text1.SelText = "Task " & CStr(I) & " terminated, " _
& "exit code: " & CStr(ExitCode) _
& ", restarting task." _
& vbNewLine
Else
Text1.SelText = "Task " & CStr(I) & " terminated, " _
& "failed to retrieve exit code, error " _
& CStr(Err.LastDllError) _
& ", restarting task." _
& vbNewLine
End If
CloseHandle Handles(I)
Handles(I) = INVALID_HANDLE
End If
End If
If Handles(I) = INVALID_HANDLE Then
Pid = Shell(Tasks(I), vbNormalFocus)
If Pid <> 0 Then
Handles(I) = OpenProcess(SYNCHRONIZE _
Or PROCESS_QUERY_INFORMATION _
Or PROCESS_TERMINATE, 0, Pid)
If Handles(I) <> 0 Then
Text1.SelText = "Task " & CStr(I) & " started." _
& vbNewLine
Else
Text1.SelText = "Task " & CStr(I) _
& ", failed to open child process." _
& vbNewLine
Handles(I) = DEAD_HANDLE
End If
Else
Text1.SelText = "Task " & CStr(I) _
& ", failed to Shell child process." _
& vbNewLine
Handles(I) = DEAD_HANDLE
End If
End If
Next
Timer1.Enabled = True
End Sub
Hopefully this helps answer the question.
something more simple will use sockets.
Launch you app server and on your client implements the communication against your server. With that you will provide intercommunication.
well i say. because i dont be what you try do
Sorry it only apply if your clients are done in house i you have the option of added changes
I found code online for something I wanted to do.
As usual, I fired it up in Visual Studio and it works no problem.
The problem occurs in that, when I try to port it over to Excel, it ceases to work.
As I understand, VBA is a watered down version of VB. (Based on reading this article:
Difference between Visual Basic 6.0 and VBA)
Therefore, how to I find out what is lost between going between the two programming environments?
To give a bit more detail:
I wrote a program in Visual Studio that sends me an email when I press a button.
I then tried to port it into Excel as a Macro, but that didn't work.
EDIT: Adeed additional problem information
Here is what I have in Visual Studio
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
CDO_Mail_Small_Text()
End Sub
Sub CDO_Mail_Small_Text()
Dim iMsg As Object
Dim iConf As Object
Dim strbody As String
Dim Flds As Object
iMsg = CreateObject("CDO.Message")
iConf = CreateObject("CDO.Configuration")
iConf.Load(-1) ' CDO Source Defaults
Flds = iConf.Fields
With Flds
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") _
= "morgan"
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
.Update()
End With
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
With iMsg
.Configuration = iConf
.To = "Jeremiah.Tantongco#Powerex.com"
.CC = ""
.BCC = ""
.From = """Ron"" <ron#something.nl>"
.Subject = "Important message"
.TextBody = strbody
.Send()
End With
End Sub
End Class
Here is what I have running in Excel:
Sub Button1_Click()
CDO_Mail_Small_Text
End Sub
Sub CDO_Mail_Small_Text()
Dim iMsg As Object
Dim iConf As Object
Dim strbody As String
Dim Flds As Object
iMsg = CreateObject("CDO.Message")
iConf = CreateObject("CDO.Configuration")
iConf.Load (-1)
Flds = iConf.Fields
With Flds
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") _
= "morgan"
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
.Update
End With
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
With iMsg
.Configuration = iConf
.To = "Jeremiah.Tantongco#Powerex.com"
.CC = ""
.BCC = ""
.From = """Ron"" <ron#something.nl>"
.Subject = "Important message"
.TextBody = strbody
.Send
End With
End Sub
The not working is a:
"Run-time error '91':
Object variable or With block variable not set"
When I debug it takes me to the following line:
"iMsg = CreateObject("CDO.Message")"
Cheers,
-Jeremiah Tantongco
VBA is a compile-on-the-fly version of Classic VB. I always thought of it as sorta halfway between Full VB 6.0 and vb script. The key is you only have access to the basic VB 6.0 libraries and other COM libraries. Because many good com libraries are almost always available (like Scripting, ADO 2.6, the Office libraries like Excel and Word, etc.) this was actually very powerful.
However this is not .NET, and you have no access to .NET libraries whatsoever. When you say Visual Studio, do you mean Visual Studio 6.0? If you're copying code from VS.NET to Excel, that has no chance of working. But if you're copying code from VS6 (or earlier) to Excel VBA, you should be able to get that working. You probably just need to reference a library you were referencing in VS. We would need more information and of course the error.
In VB6/VBA you need to use the SET statement when working with objects
Set iMsg = CreateObject("CDO.Message")
Set iConf = CreateObject("CDO.Configuration")
Can't attest to the differences in code, but the following link has great examples of sending email in VBA. Might help you figure out what is going wrong.
http://www.rondebruin.nl/sendmail.htm