|
-
Jun 8th, 2010, 01:41 PM
#1
Thread Starter
Addicted Member
[RESOLVED] WMI Win32_Service Create Fails when No User Logged On
Hello,
For some reason the following code works perfectly fine if a user is logged into a machine but if no one is logged in, I receive the error message "Call was canceled by the message filter. (Exception from HRESULT: 0x80010002 (RPC_E_CALL_CANCELED))"
I know it is possible somehow to create the service on the remote machine even if a user is not logged in but what must I change in my code??
Code:
Private Function CreateRemoteService(ByVal HostName As String, ByVal Name As String, ByVal DisplayName As String, ByVal Process As String) As Boolean
Try
Dim wmiOptions As New ConnectionOptions
wmiOptions.Impersonation = ImpersonationLevel.Impersonate
wmiOptions.Authentication = AuthenticationLevel.PacketPrivacy
Dim wmiPath As New ManagementPath("\\" & HostName & "\root\cimv2:Win32_Service")
Dim wmiScope As New ManagementScope(wmiPath, wmiOptions)
wmiScope.Connect()
Dim wmiGetOptions As New ObjectGetOptions
Dim wmi_Win32_Process_Class As New ManagementClass(wmiScope, wmiPath, wmiGetOptions)
Dim wmi_inParams As ManagementBaseObject = wmi_Win32_Process_Class.GetMethodParameters("Create")
wmi_inParams("Name") = Name
wmi_inParams("DisplayName") = DisplayName
wmi_inParams("PathName") = Process
wmi_inParams("StartMode") = "Manual"
wmi_inParams("DesktopInteract") = True
Dim wmi_outParams As ManagementBaseObject = wmi_Win32_Process_Class.InvokeMethod("Create", wmi_inParams, Nothing)
CreateRemoteService = True
Catch ex As Exception
MsgBox(ex.Message)
CreateRemoteService = False
End Try
End Function
-
Jun 8th, 2010, 01:47 PM
#2
Re: WMI Win32_Service Create Fails when No User Logged On
I know this is not directly a solution to your problem but you could try using SC.exe instead of WMI (I hate WMI precisely because of random problems like this). SC.exe is part of every version of Windows since XP (or maybe even 2000) so you can just call it straight from Process.Start.
If you open Command Prompt on your computer and just type sc /? then you will see the arguments it accepts and how to use it. You can also type a specific argument followed by /? to see more info on it, so for example the Create argument is the one you would be interested in so: sc create /?
Oh and yes you can use SC against a remote computer
-
Jun 8th, 2010, 02:19 PM
#3
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
Is there no way to call sc from a library or something instead of running another process? There has got to be some other way to do this. I didn't spend months working on re-creating PSEXEC to end up having to use a third-party executable to get the work done. LoL. If this is my only option then I guess that I will have to use SC but there must be some way!
Just F.Y.I. though Chris, I have suceeded in re-producing most of the functions that PSEXEC does in an interactive state, unfortunately, I've not been allowed to post the final code due to the copywrite issues caused by creating this application on a corporate pc. I will however, explain what I have done in as much detail as possible, and it might help others with trying to obtain the same results. I am still getting around to re-directing standard input, output, and error for processes that will be ran on the machine non-interactively. If you have a link to any examples of real time re-directing the standard input/output/error, it would be much appreciated. I have tried this before but for some reason I didn't obtain the results until after the process ended.
-
Jun 8th, 2010, 02:29 PM
#4
Re: WMI Win32_Service Create Fails when No User Logged On
 Originally Posted by taigon
Is there no way to call sc from a library or something instead of running another process? There has got to be some other way to do this. I didn't spend months working on re-creating PSEXEC to end up having to use a third-party executable to get the work done. LoL. If this is my only option then I guess that I will have to use SC but there must be some way!
lol fair enough - I dont think you can call SC directly from a library but I'm sure there will be a Windows API you can call. If not then its not actually much work to create a service yourself, its just a few registry entries, though there may be more stuff that should be done in the background that will get done when you use the API or SC.exe (I'm sure I've manually created them via registry entries in the past successfully though)
If you have a link to any examples of real time re-directing the standard input/output/error, it would be much appreciated. I have tried this before but for some reason I didn't obtain the results until after the process ended.
Some of the posts from cicatrix in this thread might be of use: http://www.vbforums.com/showthread.php?t=616099
-
Jun 8th, 2010, 02:31 PM
#5
Re: WMI Win32_Service Create Fails when No User Logged On
Here you go, CreateService API looks like it will do what you want http://msdn.microsoft.com/en-us/libr...50(VS.85).aspx
Combine it with OpenSCManager (http://msdn.microsoft.com/en-us/libr...(v=VS.85).aspx) and you should be able to get it to work remotely. I'm sure that will be what SC.exe uses internally anyway.
Personally I would much rather use those APIs than WMI. I'm probably going to add a simple .NET wrapper for those two APIs to my API Pack (http://www.vbforums.com/showthread.php?t=616861) so that it is easy for people to create services from .NET code, so if you do decide to go down the API route and get it working before me I wouldn't mind seeing some of the code
-
Jun 8th, 2010, 02:55 PM
#6
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
Thanks a lot for the links! That is my next project, to figure out the CreateService API, I only have 1 hour left at work so I may not have that done tonight, but certainly by tomorrow. I will let you know how it turns out. And that is definately a good idea, creating .NET wrappers for the API. One of these days, I will probably take all of my code and do the same.
Talk to you later.
-
Jun 8th, 2010, 03:03 PM
#7
Re: WMI Win32_Service Create Fails when No User Logged On
Cool let me know if you do get it working and good luck Not sure if I want to try get CreateService working first or try and put my theory of using NtQueryProcessInformation into use as mentioned in this thread http://www.vbforums.com/showthread.php?t=617477 ... decisions decisions.
-
Jun 8th, 2010, 03:12 PM
#8
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
I wonder if that would work for the applet I created to list the running processes on the remote machine and then continuously calculate the CPU usage using WMI...
-
Jun 8th, 2010, 03:42 PM
#9
Re: WMI Win32_Service Create Fails when No User Logged On
I'm not sure I follow you - I assume you are referring to the NtQueryInformationProcess API I mentioned but I dont think it gives you any kind of performance data - be better off using the PerformanceCounter class for that.
By the way I decided to start trying to get this NtQueryInformationProcess working before starting on CreateService but god its a pain to work with... everything in all of the structures that I have to use with it has to be declared as IntPtr and then I have to manually get the data at that address from the pointer for the values Im interested in (if that makes sense). Its probably because its an internal API and isnt really meant to be called by normal applications, just the OS itself, but there is no other API that I can find to get simple information about a process such as its parent ID or command line arguments
-
Jun 8th, 2010, 09:47 PM
#10
Re: WMI Win32_Service Create Fails when No User Logged On
Btw the problem you have was sometimes reported to be due to firewall blocking reasons.
ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ
πλάγχθη, ἐπεὶ Τροίης ἱερὸν πτολίεθρον ἔπερσεν·
-
Jun 9th, 2010, 07:32 AM
#11
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
I'm not so sure about it being a firewall dropping the connection because as soon as someone is logged into the machine, the WMI code works fine. I'm going to start working on the CreateService API.
-
Jun 9th, 2010, 10:32 AM
#12
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
Well,
Here is the class to create the remote service and it seems to work.
Code:
Imports System.Runtime.InteropServices
Public Class WindowsService
#Region "API"
'API required to open the service control manager.
Private Declare Function OpenSCManager Lib "advapi32.dll" Alias "OpenSCManagerA" (ByVal lpMachineName As String, ByVal lpDatabaseName As String, ByVal dwDesiredAccess As Integer) As Integer
'API to create the service.
Private Declare Auto Function CreateService Lib "advapi32.dll" (ByVal hSCManager As IntPtr, ByVal lpServiceName As String, ByVal lpDisplayName As String, ByVal dwDesiredAccess As Int32, ByVal dwServiceType As Int32, ByVal dwStartType As Int32, ByVal dwErrorControl As Int32, ByVal lpBinaryPathName As String, ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As Int32, ByVal lpDependencies As String, ByVal serviceStartName As String, ByVal lpPassword As String) As IntPtr
#End Region
#Region "CONST"
'Service Control Manager Security Rights
Private Const SC_MANAGER_QUERY_LOCK_STATUS = &H10
Private Const SC_MANAGER_CONNECT As Int32 = &H1
Private Const SC_MANAGER_CREATE_SERVICE As Int32 = &H2
Private Const SC_MANAGER_ENUMERATE_SERVICE As Int32 = &H4
Private Const SC_MANAGER_LOCK As Int32 = &H8
Private Const SC_MANAGER_MODIFY_BOOT_CONFIG As Int32 = &H20
Private Const SC_MANAGER_ALL_ACCESS As Int32 = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED Or _
SC_MANAGER_CONNECT Or _
SC_MANAGER_CREATE_SERVICE Or _
SC_MANAGER_ENUMERATE_SERVICE Or _
SC_MANAGER_LOCK Or _
SC_MANAGER_QUERY_LOCK_STATUS Or _
SC_MANAGER_MODIFY_BOOT_CONFIG
'Service Type Constants
Private Const SERVICE_WIN32_OWN_PROCESS As Int32 = &H10
Private Const SERVICE_INTERACTIVE_PROCESS As Int32 = &H100
'Service Startup Constants
Private Const SERVICE_DEMAND_START As Int32 = &H3
'Service Error Constants
Private Const SERVICE_ERROR_NORMAL As Int32 = &H1
#End Region
#Region "Enum"
<Flags()> Private Enum ACCESS_MASK : Uint32
DELETE = &H10000
READ_CONTROL = &H20000
WRITE_DAC = &H40000
WRITE_OWNER = &H80000
SYNCHRONIZE = &H100000
STANDARD_RIGHTS_REQUIRED = &HF0000
STANDARD_RIGHTS_READ = &H20000
STANDARD_RIGHTS_WRITE = &H20000
STANDARD_RIGHTS_EXECUTE = &H20000
STANDARD_RIGHTS_ALL = &H1F0000
SPECIFIC_RIGHTS_ALL = &HFFFF
ACCESS_SYSTEM_SECURITY = &H1000000
MAXIMUM_ALLOWED = &H2000000
GENERIC_READ = &H80000000
GENERIC_WRITE = &H40000000
GENERIC_EXECUTE = &H20000000
GENERIC_ALL = &H10000000
DESKTOP_READOBJECTS = &H1
DESKTOP_CREATEWINDOW = &H2
DESKTOP_CREATEMENU = &H4
DESKTOP_HOOKCONTROL = &H8
DESKTOP_JOURNALRECORD = &H10
DESKTOP_JOURNALPLAYBACK = &H20
DESKTOP_ENUMERATE = &H40
DESKTOP_WRITEOBJECTS = &H80
DESKTOP_SWITCHDESKTOP = &H100
WINSTA_ENUMDESKTOPS = &H1
WINSTA_READATTRIBUTES = &H2
WINSTA_ACCESSCLIPBOARD = &H4
WINSTA_CREATEDESKTOP = &H8
WINSTA_WRITEATTRIBUTES = &H10
WINSTA_ACCESSGLOBALATOMS = &H20
WINSTA_EXITWINDOWS = &H40
WINSTA_ENUMERATE = &H100
WINSTA_READSCREEN = &H200
WINSTA_ALL_ACCESS = &H37F
End Enum
'Service Security Rights
<Flags()> Private Enum SERVICE_ACCESS As UInteger
SERVICE_QUERY_CONFIG = &H1
SERVICE_CHANGE_CONFIG = &H2
SERVICE_QUERY_STATUS = &H4
SERVICE_ENUMERATE_DEPENDENTS = &H8
SERVICE_START = &H10
SERVICE_STOP = &H20
SERVICE_PAUSE_CONTINUE = &H40
SERVICE_INTERROGATE = &H80
SERVICE_USER_DEFINED_CONTROL = &H100
SERVICE_ALL_ACCESS = (ACCESS_MASK.STANDARD_RIGHTS_REQUIRED Or _
SERVICE_QUERY_CONFIG Or _
SERVICE_CHANGE_CONFIG Or _
SERVICE_ENUMERATE_DEPENDENTS Or _
SERVICE_START Or _
SERVICE_STOP Or _
SERVICE_PAUSE_CONTINUE Or _
SERVICE_INTERROGATE Or _
SERVICE_USER_DEFINED_CONTROL)
GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ Or _
SERVICE_QUERY_CONFIG Or _
SERVICE_QUERY_STATUS Or _
SERVICE_INTERROGATE Or _
SERVICE_ENUMERATE_DEPENDENTS
GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE Or _
SERVICE_CHANGE_CONFIG
GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE Or _
SERVICE_START Or _
SERVICE_STOP Or _
SERVICE_PAUSE_CONTINUE Or _
SERVICE_USER_DEFINED_CONTROL
ACCESS_SYSTEM_SECURITY = ACCESS_MASK.ACCESS_SYSTEM_SECURITY
DELETE = ACCESS_MASK.DELETE
READ_CONTROL = ACCESS_MASK.READ_CONTROL
WRITE_DAC = ACCESS_MASK.WRITE_DAC
WRITE_OWNER = ACCESS_MASK.WRITE_OWNER
End Enum
#End Region
Private Function OpenServiceController(ByVal HostName As String) As IntPtr
Dim p_SCM As IntPtr = IntPtr.Zero 'API return pointer to service control manager database.
p_SCM = OpenSCManager(HostName, Nothing, SC_MANAGER_ALL_ACCESS) 'API call to obtain handle.
Return p_SCM 'If p_SCM is nothing then call failed.
End Function
Public Function Create(ByVal HostName As String, ByVal ServiceName As String, ByVal DisplayName As String, ByVal BinaryPath As String) As IntPtr
Dim p_SCManager As IntPtr = OpenServiceController(HostName) 'Obtain pointer to service control manager database
If p_SCManager = Nothing Then
Console.WriteLine("Error obtaining pointer to SCM database: Error#" & Marshal.GetLastWin32Error.ToString)
Return Nothing
End If
'Create the service and return the pointer to the service. Value is null if call fails.
Dim p_SVCHandle As IntPtr = CreateService(p_SCManager, ServiceName, DisplayName, SERVICE_ACCESS.SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS Or SERVICE_INTERACTIVE_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, BinaryPath, Nothing, 0, Nothing, Nothing, Nothing)
Return p_SVCHandle 'Return the pointer to the service.
End Function
End Class
and here is the calling code
Code:
Dim sc As New WindowsService
Dim p_svcPtr As IntPtr = sc.Create(HostName, "nRP", "NiRDs Remote Process", "C:\Windows\System32\nRP.exe")
If p_svcPtr = Nothing Then
Invoke(InvokeStatus, "Unable to create remote service! Error#" & Marshal.GetLastWin32Error.ToString)
Invoke(InvokeDone)
Exit Sub
Else
Invoke(InvokeStatus, "Sucessfully created remote service!")
CloseServiceHandle(p_svcPtr)
end if
-
Jun 9th, 2010, 12:18 PM
#13
Re: WMI Win32_Service Create Fails when No User Logged On
Nice one and thanks for posting the code! I hadn't got round to trying to get CreateService working yet as I'm still struggling with reading the PEB (process environment block) from an external process via NtQueryInformationProcess as mentioned in the last post, so I'm sure when I come to trying to write my wrapper for CreateService your code will be a good reference 
So does it do exactly what you wanted then? even when no one is logged in?
-
Jun 9th, 2010, 12:22 PM
#14
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
I still need to test it now without someone logged into the machine but here is the complete code that replaces SC for my purposes anyway. I'm not going to post the calling code as it is self explanitory but here is the class.
Code:
Imports System.Runtime.InteropServices
Public Class WindowsService
#Region "API"
'API required to open the service control manager.
Private Declare Function OpenSCManager Lib "advapi32.dll" Alias "OpenSCManagerA" (ByVal lpMachineName As String, ByVal lpDatabaseName As String, ByVal dwDesiredAccess As Integer) As Integer
'API to create the service.
Private Declare Auto Function CreateService Lib "advapi32.dll" (ByVal hSCManager As IntPtr, ByVal lpServiceName As String, ByVal lpDisplayName As String, ByVal dwDesiredAccess As Int32, ByVal dwServiceType As Int32, ByVal dwStartType As Int32, ByVal dwErrorControl As Int32, ByVal lpBinaryPathName As String, ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As Int32, ByVal lpDependencies As String, ByVal serviceStartName As String, ByVal lpPassword As String) As IntPtr
Private Declare Auto Function StartService Lib "advapi32.dll" (ByVal hService As IntPtr, ByVal dwNumServiceArgs As Int32, ByVal lpServiceArgVectors As String) As Boolean
Private Declare Auto Function ControlService Lib "advapi32.dll" (ByVal hService As IntPtr, ByVal dwControl As Int32, ByRef lpServiceStatus As SERVICE_STATUS) As Boolean
Private Declare Auto Function QueryServiceStatus Lib "advapi32.dll" (ByVal hService As IntPtr, ByRef lpServiceStatus As SERVICE_STATUS) As Boolean
Private Declare Auto Function DeleteService Lib "advapi32.dll" (ByVal hService As IntPtr) As Boolean
#End Region
#Region "CONST"
'Service Control Manager Security Rights
Private Const SC_MANAGER_QUERY_LOCK_STATUS = &H10
Private Const SC_MANAGER_CONNECT As Int32 = &H1
Private Const SC_MANAGER_CREATE_SERVICE As Int32 = &H2
Private Const SC_MANAGER_ENUMERATE_SERVICE As Int32 = &H4
Private Const SC_MANAGER_LOCK As Int32 = &H8
Private Const SC_MANAGER_MODIFY_BOOT_CONFIG As Int32 = &H20
Private Const SC_MANAGER_ALL_ACCESS As Int32 = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED Or _
SC_MANAGER_CONNECT Or _
SC_MANAGER_CREATE_SERVICE Or _
SC_MANAGER_ENUMERATE_SERVICE Or _
SC_MANAGER_LOCK Or _
SC_MANAGER_QUERY_LOCK_STATUS Or _
SC_MANAGER_MODIFY_BOOT_CONFIG
'Service Type Constants
Private Const SERVICE_WIN32_OWN_PROCESS As Int32 = &H10
Private Const SERVICE_INTERACTIVE_PROCESS As Int32 = &H100
'Service Startup Constants
Private Const SERVICE_DEMAND_START As Int32 = &H3
'Service Error Constants
Private Const SERVICE_ERROR_NORMAL As Int32 = &H1
#End Region
#Region "Enum"
<Flags()> Private Enum ACCESS_MASK : Uint32
DELETE = &H10000
READ_CONTROL = &H20000
WRITE_DAC = &H40000
WRITE_OWNER = &H80000
SYNCHRONIZE = &H100000
STANDARD_RIGHTS_REQUIRED = &HF0000
STANDARD_RIGHTS_READ = &H20000
STANDARD_RIGHTS_WRITE = &H20000
STANDARD_RIGHTS_EXECUTE = &H20000
STANDARD_RIGHTS_ALL = &H1F0000
SPECIFIC_RIGHTS_ALL = &HFFFF
ACCESS_SYSTEM_SECURITY = &H1000000
MAXIMUM_ALLOWED = &H2000000
GENERIC_READ = &H80000000
GENERIC_WRITE = &H40000000
GENERIC_EXECUTE = &H20000000
GENERIC_ALL = &H10000000
DESKTOP_READOBJECTS = &H1
DESKTOP_CREATEWINDOW = &H2
DESKTOP_CREATEMENU = &H4
DESKTOP_HOOKCONTROL = &H8
DESKTOP_JOURNALRECORD = &H10
DESKTOP_JOURNALPLAYBACK = &H20
DESKTOP_ENUMERATE = &H40
DESKTOP_WRITEOBJECTS = &H80
DESKTOP_SWITCHDESKTOP = &H100
WINSTA_ENUMDESKTOPS = &H1
WINSTA_READATTRIBUTES = &H2
WINSTA_ACCESSCLIPBOARD = &H4
WINSTA_CREATEDESKTOP = &H8
WINSTA_WRITEATTRIBUTES = &H10
WINSTA_ACCESSGLOBALATOMS = &H20
WINSTA_EXITWINDOWS = &H40
WINSTA_ENUMERATE = &H100
WINSTA_READSCREEN = &H200
WINSTA_ALL_ACCESS = &H37F
End Enum
'Service Security Rights
<Flags()> Private Enum SERVICE_ACCESS As UInteger
SERVICE_QUERY_CONFIG = &H1
SERVICE_CHANGE_CONFIG = &H2
SERVICE_QUERY_STATUS = &H4
SERVICE_ENUMERATE_DEPENDENTS = &H8
SERVICE_START = &H10
SERVICE_STOP = &H20
SERVICE_PAUSE_CONTINUE = &H40
SERVICE_INTERROGATE = &H80
SERVICE_USER_DEFINED_CONTROL = &H100
SERVICE_ALL_ACCESS = (ACCESS_MASK.STANDARD_RIGHTS_REQUIRED Or _
SERVICE_QUERY_CONFIG Or _
SERVICE_CHANGE_CONFIG Or _
SERVICE_ENUMERATE_DEPENDENTS Or _
SERVICE_START Or _
SERVICE_STOP Or _
SERVICE_PAUSE_CONTINUE Or _
SERVICE_INTERROGATE Or _
SERVICE_USER_DEFINED_CONTROL Or _
SERVICE_QUERY_STATUS)
GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ Or _
SERVICE_QUERY_CONFIG Or _
SERVICE_QUERY_STATUS Or _
SERVICE_INTERROGATE Or _
SERVICE_ENUMERATE_DEPENDENTS
GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE Or _
SERVICE_CHANGE_CONFIG
GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE Or _
SERVICE_START Or _
SERVICE_STOP Or _
SERVICE_PAUSE_CONTINUE Or _
SERVICE_USER_DEFINED_CONTROL
ACCESS_SYSTEM_SECURITY = ACCESS_MASK.ACCESS_SYSTEM_SECURITY
DELETE = ACCESS_MASK.DELETE
READ_CONTROL = ACCESS_MASK.READ_CONTROL
WRITE_DAC = ACCESS_MASK.WRITE_DAC
WRITE_OWNER = ACCESS_MASK.WRITE_OWNER
End Enum
'Service states
Public Enum SERVICE_STATE
SERVICE_CONTINUE_PENDING = &H5
SERVICE_PAUSE_PENDING = &H6
SERVICE_PAUSED = &H7
SERVICE_RUNNING = &H4
SERVICE_START_PENDING = &H2
SERVICE_STOP_PENDING = &H3
SERVICE_STOPPED = &H1
End Enum
#End Region
#Region "Struct"
Public Structure SERVICE_STATUS
Public dwServiceType As Int32
Public dwCurrentState As Int32
Public dwControlsAccepted As Int32
Public dwWin32ExitCode As Int32
Public dwServiceSpecificExitCode As Int32
Public dwCheckPoint As Int32
Public dwWaitHint As Int32
End Structure
#End Region
Private Function OpenServiceController(ByVal HostName As String) As IntPtr
Dim p_SCM As IntPtr = IntPtr.Zero 'API return pointer to service control manager database.
p_SCM = OpenSCManager(HostName, Nothing, SC_MANAGER_ALL_ACCESS) 'API call to obtain handle.
Return p_SCM 'If p_SCM is nothing then call failed.
End Function
Public Function Create(ByVal HostName As String, ByVal ServiceName As String, ByVal DisplayName As String, ByVal BinaryPath As String) As IntPtr
Dim p_SCManager As IntPtr = OpenServiceController(HostName) 'Obtain pointer to service control manager database
If p_SCManager = Nothing Then
Console.WriteLine("Error obtaining pointer to SCM database: Error#" & Marshal.GetLastWin32Error.ToString)
Return Nothing
End If
'Create the service and return the pointer to the service. Value is null if call fails.
Dim p_SVCHandle As IntPtr = CreateService(p_SCManager, ServiceName, DisplayName, SERVICE_ACCESS.SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS Or SERVICE_INTERACTIVE_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, BinaryPath, Nothing, 0, Nothing, Nothing, Nothing)
Return p_SVCHandle 'Return the pointer to the service.
End Function
Public Function Start(ByVal p_Service As IntPtr) As Boolean
If StartService(p_Service, 0, Nothing) = True Then
Return True
Else
Console.WriteLine("Error starting service: Error#" & Marshal.GetLastWin32Error.ToString)
Return False
End If
End Function
Public Function cStop(ByVal p_Service As IntPtr) As Boolean
Dim ss As New SERVICE_STATUS
ss = Control(p_Service, &H1)
If ss.dwCurrentState = Nothing Then
Return False
Else
Return True
End If
End Function
Public Function Delete(ByVal p_Service As IntPtr) As Boolean
If DeleteService(p_Service) = True Then
Return True
Else
Console.WriteLine("Error deleting service: Error#" & Marshal.GetLastWin32Error.ToString)
Return False
End If
End Function
Public Function Control(ByVal p_Service As IntPtr, ByVal ControlCode As Int32) As SERVICE_STATUS
Dim SS As New SERVICE_STATUS
If ControlService(p_Service, ControlCode, SS) = True Then
Control = SS
Else
Console.WriteLine("Error controlling service: Error#" & Marshal.GetLastWin32Error.ToString)
Control = Nothing
End If
End Function
Public Function GetStatus(ByVal p_Service As IntPtr) As SERVICE_STATUS
Dim SS As New SERVICE_STATUS
If QueryServiceStatus(p_Service, SS) = True Then
GetStatus = SS
Else
Console.WriteLine("Error querying service status: Error#" & Marshal.GetLastWin32Error.ToString)
GetStatus = Nothing
End If
End Function
End Class
-
Jun 9th, 2010, 12:24 PM
#15
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
Maybe you can also help me find some API that will allow me to check who the currently logged in user is and if no user is logged in, to report that back to me. I'm currently using WMI, but yet again, it seems to be quite unstable. It works on most machines when a user is logged in but when no one is logged in, the calls fail.
Code:
Public Function GetCurrentUser() As Boolean
Try
Dim MyConnectionOptions As New System.Management.ConnectionOptions
MyConnectionOptions.Authentication = AuthenticationLevel.Connect
MyConnectionOptions.EnablePrivileges = True
MyConnectionOptions.Impersonation = ImpersonationLevel.Impersonate
Dim MScope As New ManagementScope("\\" & HostName & "\root\cimv2")
Dim OQ As New ObjectQuery("SELECT * FROM WIN32_ComputerSystem")
Dim MS As New ManagementObjectSearcher(MScope, OQ)
Dim MC As ManagementObjectCollection = Nothing
Try
MC = MS.Get
Catch ex As System.Runtime.InteropServices.COMException
If ex.Message = "The RPC server is unavailable." And ex.Source = "System.Management" Then
MsgBox("The machine may be shutdown or RPC Server is not running on that machine.")
End If
Catch ex As Exception
MsgBox("Other" & ex.ToString)
End Try
Dim MO As ManagementObject
For Each MO In MC
CurrentUser = MO("UserName")
Exit For
Next
Return True
Catch ex As Exception
If ex.Message = "Object reference not set to an instance of an object." And ex.Source = "NiRDs" Then
MsgBox(HostName & " no user is currently logged in!")
rdoCurrent.Visible = False
cbInteractive.Checked = False
cbInteractive.Visible = False
rdoSystemAccount.Checked = True
Else
MsgBox(ex.ToString)
Me.Dispose()
End If
End Try
Return False
End Function
-
Jun 9th, 2010, 12:27 PM
#16
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
I just tried using this to create a process on the remote machine while no one is logged in, and it worked perfectly! now to start working on re-directing the input/output/error. Also I still need to validate whether or not a user is logged in to determine an interactive process or not.
-
Jun 9th, 2010, 04:55 PM
#17
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
Actually, I finally created a class that will return the first logged on user which should work for what I need to do
Code:
Imports System.Net.NetworkInformation
Imports System.Text
Imports System.Collections.Specialized
Imports System.Runtime.InteropServices
Public Class NetworkTools
#Region "API"
' ******** Code Start ********
' -----------------------
' The code for retrieving remote user name was
' translated into VBA from source code provided by
' SysInternals - www.sysinternals.com
' Copyright (C) 1999-2000 Mark Russinovich
' as part of the LoggedOn console app
'
' Translated by: Dev Ashish
' www.mvps.org/access
'
' This code was originally written by Dev Ashish.
' It is not to be altered or distributed,
' except as part of an application.
' You are free to use it in any application,
' provided the copyright notice is left unchanged.
'
' Modified version 2003-26-03 by Andreas Schubert
' See description of fGetRemoteLoggedUserID function for details
Private Declare Function apiNetAPIBufferFree Lib "netapi32.dll" Alias "NetApiBufferFree" (ByVal buffer As Long) As Long
Private Declare Function apiFormatMsgLong Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, ByVal lpSource As Long, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, ByVal Arguments As Long) As Long
Private Declare Auto Function RegConnectRegistry Lib "Advapi32" (ByVal lpMachineName As String, ByVal hKey As IntPtr, ByRef phkResult As IntPtr) As Integer
Private Declare Auto Function RegEnumKeyEx Lib "Advapi32" (ByVal hKey As IntPtr, ByVal dwIndex As Integer, ByVal lpName As StringBuilder, ByRef lpcName As Integer, ByVal lpReserved As IntPtr, ByVal lpClass As IntPtr, ByVal lpcClass As IntPtr, ByVal lpftLastWriteTime As IntPtr) As Integer
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As IntPtr) As Integer
Private Declare Function AllocateAndInitializeSid Lib "advapi32.dll" (ByRef pIdentifierAuthority As SID_IDENTIFIER_AUTHORITY, ByVal nSubAuthorityCount As Byte, ByVal nSubAuthority0 As Integer, ByVal nSubAuthority1 As Integer, ByVal nSubAuthority2 As Integer, ByVal nSubAuthority3 As Integer, ByVal nSubAuthority4 As Integer, ByVal nSubAuthority5 As Integer, ByVal nSubAuthority6 As Integer, ByVal nSubAuthority7 As Integer, ByRef lpPSid As IntPtr) As Integer
Private Declare Function LookupAccountSid Lib "advapi32.dll" Alias "LookupAccountSidA" (ByVal systemName As String, ByVal psid As IntPtr, ByVal accountName As String, ByRef cbAccount As Integer, ByVal domainName As String, ByRef cbDomainName As Integer, ByRef use As Integer) As Integer
Private Declare Function apiIsValidSid Lib "advapi32.dll" Alias "IsValidSid" (ByVal pSid As String) As Long
Private Declare Function FreeSid Lib "advapi32.dll" (ByVal pSid As IntPtr) As IntPtr
#End Region
#Region "Struct"
Private Structure FILETIME
Public dwLowDateTime As Long
Public dwHighDateTime As Long
End Structure
Public Structure SID_IDENTIFIER_AUTHORITY
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=6)> Dim Value() As Byte
End Structure
#End Region
#Region "CONST"
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Private Const ERROR_SUCCESS = 0&
Private Const HKEY_USERS = &H80000003
Private Const MAX_REG_KEYNAME_SIZE = 260
Private Const ERROR_MORE_DATA = 234
Private Const MAX_NAME_STRING = 1024
Private Const SECURITY_NT_AUTHORITY = 5
#End Region
Public Shared Function fGetRemoteLoggedUserID(ByVal strMachineName As String) As String
'
' Retrieves the id of the user currently logged into the specified
' local or remote machine in the format DOMAIN\UserName
'
' Usage:
' ?fGetRemoteLoggedUserID("springfield")
'
' Retrieves the id of the user currently logged into the specified
' local or remote machine in the format DOMAIN\UserName
'
' Translated into VBA from source code provided by
' SysInternals - www.sysinternals.com
' Copyright (C) 1999-2000 Mark Russinovich
' as part of the LoggedOn console app
'
' Translated by: Dev Ashish
' www.mvps.org/access
' [email protected]
'
'
' modified 2003-26-03 by: Andreas Schubert
' [email protected]
' eliminated a view bugs:
' 1. converting the registry subkey to SubAuthorities sometimes caused an
' overflow error because of the difference between C's DWORD and VB's Long.
' so I first convert them to a double and if it exceeds 2147483647,
' I substract 4294967296 and then convert it to long
' For j = 3 To lngSubAuthorityCount
' adblTemp = 0
' adblTemp = CDbl(astrTmpSubAuthority(j))
' If adblTemp > 2147483647 Then
' adblTemp = adblTemp - 4294967296#
' End If
' alngSubAuthority(j - 3) = CLng(adblTemp)
' Next
'
' 2. sometimes a subkey won't consist of 7 parts. If so, the function
' crashed with an Index error.
' Solving this was pretty easy by inserting
' If UBound(alngSubAuthority) < 7 Then ReDim Preserve alngSubAuthority(7)
'
' 3. It is possible that the function finds more than 1 active user
' at the remote workstation. This may for instance be the cause
' if you are running an Microsoft SMS Server in your network.
' The SMS client will run under an local account on your machine
' (like \Computername\SMSCliSvsAcct)
' So, I modified the function to get all accounts separated by vbcrlf - character(s)
'
Dim p_RemoteUser As IntPtr = IntPtr.Zero
Dim j As Long
Dim lRet As Long, i As Long
Dim alngSubAuthority() As Long, astrTmpSubAuthority() As String
Dim ntAuthority As New SID_IDENTIFIER_AUTHORITY
Dim pSid As IntPtr, lngUserNameSize As Long, lngDomainNameSize As Long
Dim lngSubAuthorityCount As Long, intSidType As Integer
Dim strUserName As String, strDomainName As String, strSubKeyName As String
Dim sc As New StringCollection
Dim sb As New StringBuilder(MAX_REG_KEYNAME_SIZE + 1)
Dim NameSize As Integer
Dim adblTemp As Double
Const ERR_GENERIC = vbObjectError + 5555
Const KEY_TO_SKIP_1 = "classes"
Const KEY_TO_SKIP_2 = ".default"
lRet = RegConnectRegistry("\\" & strMachineName, New IntPtr(HKEY_USERS), p_RemoteUser)
If lRet <> ERROR_SUCCESS Then
Throw New Exception(ERR_GENERIC)
End If
ReDim ntAuthority.Value(6)
ntAuthority.Value(5) = SECURITY_NT_AUTHORITY
i = 0
strSubKeyName = New String(vbNullChar, NameSize)
NameSize = MAX_REG_KEYNAME_SIZE + 1
lRet = RegEnumKeyEx(p_RemoteUser, i, sb, NameSize, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
Do While (lRet = ERROR_SUCCESS Or lRet = ERROR_MORE_DATA)
If (InStr(1, sb.ToString, KEY_TO_SKIP_1, CompareMethod.Text) = 0 And InStr(1, sb.ToString, KEY_TO_SKIP_2, CompareMethod.Text) = 0) Then
strSubKeyName = Strings.Left(sb.ToString, NameSize)
astrTmpSubAuthority = Split(strSubKeyName, "-")
lngSubAuthorityCount = UBound(astrTmpSubAuthority)
ReDim alngSubAuthority(lngSubAuthorityCount)
For j = 3 To lngSubAuthorityCount
adblTemp = 0
adblTemp = CDbl(astrTmpSubAuthority(j))
If adblTemp > 2147483647 Then
adblTemp = adblTemp - 4294967296.0#
End If
alngSubAuthority(j - 3) = CLng(adblTemp)
Next
lngSubAuthorityCount = UBound(alngSubAuthority) - 2
If UBound(alngSubAuthority) < 7 Then ReDim Preserve alngSubAuthority(7)
If (AllocateAndInitializeSid(ntAuthority, CByte(lngSubAuthorityCount), alngSubAuthority(0), alngSubAuthority(1), alngSubAuthority(2), alngSubAuthority(3), alngSubAuthority(4), alngSubAuthority(5), alngSubAuthority(6), alngSubAuthority(7), pSid)) Then
If (apiIsValidSid(pSid)) Then
lngUserNameSize = MAX_NAME_STRING
lngDomainNameSize = MAX_NAME_STRING
strUserName = New String(vbNullChar, lngUserNameSize - 1)
strDomainName = New String(vbNullChar, lngDomainNameSize - 1)
lRet = LookupAccountSid(strMachineName, pSid, strUserName, lngUserNameSize, strDomainName, lngDomainNameSize, intSidType)
If fTrimNull(strDomainName) <> "NT AUTHORITY" Then
FreeSid(pSid)
RegCloseKey(p_RemoteUser)
Return fTrimNull(strDomainName) & "\" & fTrimNull(strUserName)
End If
End If
End If
FreeSid(pSid)
End If
i = i + 1
NameSize = MAX_REG_KEYNAME_SIZE + 1
strSubKeyName = New String(vbNullChar, NameSize)
lRet = RegEnumKeyEx(p_RemoteUser, i, sb, NameSize, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
Loop
RegCloseKey(p_RemoteUser)
Return Nothing
End Function
Private Shared Function fTrimNull(ByVal strIn As String) As String
Dim intPos As Integer
intPos = InStr(1, strIn, vbNullChar)
If intPos Then
fTrimNull = Mid$(strIn, 1, intPos - 1)
Else
fTrimNull = strIn
End If
End Function
End Class
-
Jun 9th, 2010, 05:25 PM
#18
Re: WMI Win32_Service Create Fails when No User Logged On
Cool I'm sure you could eliminate half of the API stuff in there and replace it with built in .NET methods though - like anything to do with reading the registry for example (which accounts for a fair bit of that code)
-
Jun 10th, 2010, 08:23 AM
#19
Thread Starter
Addicted Member
Re: WMI Win32_Service Create Fails when No User Logged On
Well it seems to work so I'm not going to change it right now, lol. I'm going to start working on re-directing the input for remote process through the named pipe, to my client application....fuuuuun....I'm going to close this post and will re-post if need be
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|