.vbs file not working properly from windows service - c++

I created a windows service in C++ which runs a VBScript file on a particular event. This works fine when I do this from a Win32 application in C++, but doesn't work the same way from windows service.
Code of CPP file:
SHELLEXECUTEINFO ExecuteInfo;
memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
ExecuteInfo.cbSize = sizeof(ExecuteInfo);
ExecuteInfo.fMask = 0;
ExecuteInfo.hwnd = 0;
ExecuteInfo.lpVerb = _T("open"); // Operation to perform
ExecuteInfo.lpFile = _T("D:\\demo.vbs"); // Application name
ExecuteInfo.lpParameters = 0; // Additional parameters
ExecuteInfo.lpDirectory = 0; // Default directory
ExecuteInfo.nShow = SW_SHOW;
ExecuteInfo.hInstApp = 0;
if(ShellExecuteEx(&ExecuteInfo) == FALSE)
{
}

Assuming objShell.Windows is an instance of "Shell.Application", what you get is according to msdn
ShellWindows object: Represents a collection of the open windows that
belong to the Shell. Methods associated with this objects can control
and execute commands within the Shell, and obtain other Shell-related
objects.
The critical part is that belong to the Shell. Your problem is that the shell in your desktop is different from the shell that the services in your machine have.
Services run in a separate session.
So, your script is correctly working. It doesn't return any shell window because there is no one in the session where the services are running.

I created a normal exe instead of windows service and added that to windows startup registory.
That way i was able to achieve desired.

Related

How do I run a program from cpp the same way as I would do it via launch as admin in explorer?

I'm unpacking a executable from my UWP application and storing them in the LocalState folder. Then I launch a dedicated fullTrust utility and try to execute this program as administrator. This fails.
If and only if I launch the same exe via the explorer, by clicking on "Run as administrator" it works.
With other exe which are lying in different folders it works flawless.
The code I'm using to launch is:
SHELLEXECUTEINFO shExInfo;
ZeroMemory(&shExInfo, sizeof(shExInfo));
shExInfo.cbSize = sizeof(shExInfo); // structure size
shExInfo.fMask = mask; // execution flags
shExInfo.lpVerb = _T("runas"); // run elevated
shExInfo.lpFile = szExe; // application to start
shExInfo.lpParameters = params; // some params
shExInfo.lpDirectory = nullptr; // current working directory
shExInfo.nShow = show; // show/hide the application
ShellExecuteEx(&shExInfo) // This returns false, thus meaning a failure to start the exe
Why is it failing if I launch it as administrator from my cpp, but not from explorer. And how do I solve this problem?
Turns out my code works the way I expected it, the problem was that it was parsing the path incorrectly, thus failing to launch it.

Changing the Network adapter name Programmatically in windows with Qt

I know that it is possible to change the network adapter in windows using the netsh command in console. but I need to do this in Qt using C++. I have tried to use QProcess to call netsh but command prompt needs admin right. also there is space in my adapter name that make it also not easy to run. Is there any library in Qt capable of changing Network adapter name without using QProcess and calling windows commands in it?
Update 1:
When I run the program with admin right and set the \" for having " inside of my string I can change the adapter name, using QProcess and netsh command.
QProcess p;
QString pi_network = "original adapter name";
p.start("netsh interface set interface name = \""+pi_network+"\" newname = \"MyAdapter\"");
I will post it as an answer, because it might help someone (as MrEricSir said in the comments).
you can use netsh command, but be aware that you should run your program with administrator right in windows.
QProcess p;
QString pi_network = "original adapter name";
p.start("netsh interface set interface name = \""+pi_network+"\" newname = \"new network adapter name\"");
p.waitForFinished();
p.close();

Inject Jar and replace classes in running JVM

I want to be able to replace and add some classes to an already running JVM. I read that I need to use CreateRemoteThread, but I don't completely get it. I read this post on how to do it (Software RnD), but I can't figure out what it does and why. Besides that, it only introduces new classes, but doesn't change existing ones. How can I do it with C++?
You don't even need CreateRemoteThread - there is an official way to connect to remote JVM and replace loaded classes by using Attach API.
You need a Java Agent that calls Instrumentation.redefineClasses.
public static void agentmain(String args, Instrumentation instr) throws Exception {
Class oldClass = Class.forName("org.pkg.MyClass");
Path newFile = Paths.get("/path/to/MyClass.class");
byte[] newData = Files.readAllBytes(newFile);
instr.redefineClasses(new ClassDefinition(oldClass, newData));
}
You'll have to add MANIFEST.MF with Agent-Class attribute and pack the agent into a jar file.
Then use Dynamic Attach to inject the agent jar into the running VM (with process ID = pid).
import com.sun.tools.attach.VirtualMachine;
...
VirtualMachine vm = VirtualMachine.attach(pid);
try {
vm.loadAgent(agentJarPath, options);
} finally {
vm.detach();
}
A bit more details in the article.
If you insist on using C/C++ instead of Java API, you may look at my jattach utility.

Run an executable as service in C++

I created a Win32Console application using MSVS2013 and it was compiled successfully. Now I tried creating a service using CreateService and binary path was set to the path of the above produced executable. Though I was able to create the service, I cannot start it using StartService. The error code 1053 is thrown each time. I tried using sc.exe and also tried to start the service manually from Services. The same error is shown. How can I solve it now?
You must create a ServiceMain.
Here is a sample.
If you want to execute a non-service application you can use psexec.
You have collision with SC- manager and your function inside application start service
your name of the function service dispatcher table for service;)
prevent from error 1053 if call was send not from SC - manager
C++ code:
if(argc < 2)
{
if(!Service_Dispatcher_Table())
{
std::cout<<"ERROR :"<< GetLastError();
}
}
else
{
//your command line "argc"
}
//here your commands or function : startservice();

WinAPI NetUserGetInfo() fails with NERR_UserNotFound error code on Active Directory domain

I'm running the following piece of code from a local service application. The purpose is to obtain the path to a user's profile before calling LoadUserProfile() to load that user's profile before calling CreateProcessAsUser() to run a user-mode process on behalf of that user.
Note that this question is not about LoadUserProfile(), or CreateProcessAsUser().
What happens is this. When the code below is run on Windows XP w/SP3 that is a part of the Active Directory domain, with a single user logged in via a local console (that user's session ID is used below) the NetUserGetInfo() API fails. Also note that it works fine in any other circumstance:
//'dwSessID' = session ID of the user to retrieve a user profile path for
LPTSTR pUserName = NULL;
DWORD dwcbSzUserName = 0;
if(!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessID, WTSUserName, &pUserName, &dwcbSzUserName))
{
//Error
return false;
}
USER_INFO_4* pUI4 = NULL;
DWORD dwNetStatus;
if((dwNetStatus = NetUserGetInfo(NULL, pUserName, 4, (BYTE**)&pUI4)) == NERR_Success)
{
PROFILEINFO pfi = {0};
pfi.dwSize = sizeof(pfi);
pfi.lpUserName = pUserName;
pfi.dwFlags = PI_NOUI;
pfi.lpProfilePath = pUI4->usri4_profile;
LoadUserProfile(hToken, &pfi);
//And so on
}
else
{
//On that specific machine I get here with 'dwNetStatus' = 2221,
//or NERR_UserNotFound, that according to MSDN is
//"The user name could not be found."
//Also note that GetLastError is not used for this API.
}
Can some suggest why can NetUserGetInfo() fail on that particular machine, and how to fix this code?
PS. I know that MSDN for NetUserGetInfo states that there might be issues with a ACL on Active Directory domain, but it doesn't specify how to set one...
If I read the documentation for NetUserGetInfo, for the information level of the data you code 4 . It's written Level 4 Return detailed information and additional attributes about the user account. This level is valid only on servers. As far as I understand it's not your case. Do you verify the value of pUserName returned by WTSQuerySessionInformation.
As JPBlanc stated NetUserGetInfo with level 4 is valid only on servers.
Another problem is that you retrieve the name of the logged on user, but not the domain the user belongs to.
Noticed you are calling NetUserGetInfo with pUserName the type of LPTSTR.
Sometimes it won't work (if you will compile your project to use ANSII strings by default).
Consider changing you string types to LPWSTR.