|
The trick that has worked for me is not to define the file names as pointers but rather as arrays.
Regards,
Alf Stockton
|
|
|
|
|
Whether you use
char *NewName = "c:\\somefile.txt";
remove(NewName); or
char NewName[] = "c:\\somefile.txt";
remove(NewName); they both work.
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
I have just run this code and it works fine, so I suspect there is some part that you have not shown that is actually failing. Can you post the full program (assuming it's not hundreds of lines)? Also please surround it with <pre></pre> tags to keep it formatted properly, use the code block button at the top of the edit window.
|
|
|
|
|
Name file variables as arrays not pointers.
Regards,
Alf Stockton
|
|
|
|
|
Hello All,
I am working on a project where I need to catch the windows shutdown event through a windows service running in system account, delay shutdown and execute some shutdown scripts and then once the scripts have been completed the shutdown continues.Kindly suggest me some ways to do this via a windows service developed by me in C++.
Regards,
Kushagra
I hate coding but I luv to develop 
|
|
|
|
|
Have you tried creating a hidden window and handling the WM_QUERYENDSESSION message? You may need to turn on the "Allow Service to Interact With Desktop" option.
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
Did you try my suggestions from when you asked this question in September 2009[^]?
Best Wishes,
-David Delaune
|
|
|
|
|
Hello David,
I definitely had tried the the function but some how it doesnt seem to work for me.Can you detail me exactly what steps have to be followed in achieving the same.
Regards,
Kushagra
|
|
|
|
|
Kushagra Tiwari wrote: Can you detail me exactly what steps have to be followed in achieving the same.
First can you tell me what operating system will be hosting the Windows service?
Best Wishes,
-David Delaune
|
|
|
|
|
I have to run this in all operating systems namely Windows XP, Windows Server 2003& 2008, Windows Vista,Windows 7. I tried it presently on XP , but the application is meant to be supporting all flavours of Windows after NT
Regards,
Kushagra
|
|
|
|
|
Hi Kushagra,
This means that you will need to conditionally delay the shutdown based on what operating system the service is running on. There have been some changes in how a shutdown works in Vista and above. These changes are documented here:
Application Shutdown Changes in Windows Vista[^]
I would suggest creating a hidden window in each interactive logon session and returning FALSE when the window recieves a WM_QUERYENDSESSION message. On Vista and above you will need to call ShutdownBlockReasonCreate before returning FALSE to the WM_QUERYENDSESSION message.
Best Wishes,
-David Delaune
|
|
|
|
|
Also to call Abort shutdown Method my service first needs to know that a shutdown signal was received. So kindly tell me how my service will come to know about that a shutdown signal was received and where should I place a call to abortshutdown ?
Regards,
Kushagra
|
|
|
|
|
To catch the Shutdown-Event you have to handle SERVICE_CONTROL_SHUTDOWN or SERVICE_CONTROL_PRESHUTDOWN
event in your HandlerEx callback function you registered with RegisterServiceCtrlHandlerEx.
(To use this, you need to say the system that your service supports shutdown events.
An other possibility is to use the SetConsoleCtrlHandler function where you handle the CTRL_SHUTDOWN_EVENT event in your HandlerRoutine.
After you catched the shutdown-event you have to use the function AbortSystemShutdown or just
delay your service-shutdown for example with the status SERVICE_STOP_PENDING.
|
|
|
|
|
Thanks Covean,
I will try todo this and will let u know as I think this should actually work out
Regards,
Kushagra
|
|
|
|
|
Covean wrote: An other possibility is to use the SetConsoleCtrlHandler function...
Isn't this for console applications?
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
See http://msdn.microsoft.com/en-us/library/ms683240(VS.85).aspx
Its also a good reference about service shutdown.
"Services can also use the SetConsoleCtrlHandler function to receive shutdown notification. This notification is received when the running applications are shutting down, which occurs before services are shut down."
|
|
|
|
|
Hello Covean,
As per your suggesstion I did the folowing things:
In ServiceMain of my service I did the following code :
m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
if (m_hServiceStatus == NULL)
{
LogEvent(_T("Handler not installed"));
return;
}
and here is the code for _Handler function :
void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
{
char chComputerName[512];
DWORD dwBuff = 512;
GetComputerName(chComputerName,&dwBuff);
if (dwOpcode == SERVICE_CONTROL_SHUTDOWN)
{
AbortShutdown(chComputerName);
}
_Module.Handler(dwOpcode);
}
and abortshutdown does the following functionality
BOOL AbortShutdown(LPTSTR lpMachineName)
{
HANDLE hToken; // handle to process token
TOKEN_PRIVILEGES tkp; // pointer to token structure
BOOL fResult; // system shutdown flag
// Get the current process token handle so we can get shutdown
// privilege.
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
// TRACE("OpenProcessToken failed.\n");
return false;
}
// Get the LUID for shutdown privilege.
LookupPrivilegeValue(lpMachineName, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get shutdown privilege for this process.
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES)NULL, 0);
// Cannot test the return value of AdjustTokenPrivileges.
if (GetLastError() != ERROR_SUCCESS)
{
//TRACE("AdjustTokenPrivileges(setting) enable failed.\n");
return false;
}
// Prevent the system from shutting down.
fResult = AbortSystemShutdown(lpMachineName);
if (!fResult)
{
//TRACE("AbortSystemShutdown failed.\n");
return false;
}
else
{
Cxcutter objexe;
}
//m_bIsShuttingDown = false; // Reset shut down flag
// Disable shutdown privilege.
tkp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
{
// TRACE("AdjustTokenPrivileges(re-setting) disable failed.\n");
return false;
}
return true;
}
But some how the when shutdown is done then the control never comes to this and windows shuts down normailly
Please suggest some thing If I am going wrong somewhere.
Regards,
Kushagra
modified on Thursday, October 22, 2009 11:35 AM
|
|
|
|
|
Does your service get the shutdown notification SERVICE_CONTROL_SHUTDOWN or does AbortSystemShutdown not abort the shutdown?
I would say its easier to test the version with SetConsoleCtrl..., after that you should try th service version.
Edit:
In my first answer I said, that you have to say the system that your service supports SHUTDOWN events.
Now I found what i meant. You have to use SetServiceStatus with a SERVICE_STATUS where dwControlsAccepted is a least SERVICE_ACCEPT_SHUTDOWN.
modified on Thursday, October 22, 2009 12:02 PM
|
|
|
|
|
Ok , I will try with this and attempt achieve the same
|
|
|
|
|
Covean wrote: . You have to use SetServiceStatus with a SERVICE_STATUS where dwControlsAccepted is a least SERVICE_ACCEPT_SHUTDOWN.
As per ur suggestion I tried to do the same but seems the control never reaches my code , I am quite confused actually as I think I am doing every thing which I think is right .Here is what I am doing after calling RegisterserverEx:
::SetServiceStatus(m_hServiceStatus, &m_status);
Where m_status is of SERVICE_STATUS type and initialized by :
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
m_status.dwCurrentState = SERVICE_STOPPED;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
m_status.dwWin32ExitCode = 0;
m_status.dwServiceSpecificExitCode = 0;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;
and in Handler function of my Service handle SERVICE_CONTROL_SHUTDOWN which has following code
char chComputerName[512];
DWORD dwBuff = 512;
GetComputerName(chComputerName,&dwBuff);
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
SetServiceStatus(SERVICE_STOP_PENDING);
Alive = true;
iscmcontrol = 3;
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
break;
case SERVICE_CONTROL_PAUSE:
Alive = false;
iscmcontrol = 1;
break;
case SERVICE_CONTROL_CONTINUE:
Alive = false;
iscmcontrol = 0;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
CoInitialize( NULL );
AbortShutdown(chComputerName);
CoUninitialize();
Alive = true;
iscmcontrol = 2;
break;
default:
LogEvent(_T("Bad service request"));
}
If you want the sample code and personally see what is the problem please let me know your email address I will send it to you .
Regards,
Kushagra
|
|
|
|
|
Hello Covean,
Did you recieve my mail having the sample code??
Kushagra
|
|
|
|
|
Yes I received your code and after some changes (for VS2008 and Vista) I has installed it. Now I'm try to get it to work.
|
|
|
|
|
Ok . I hope it works
Kushagra
|
|
|
|
|
Any luck with the code?
Regards,
Kushagra
|
|
|
|
|
What OS to you use? Cause on Vista I do not find any way to block the shutdown (ShutdownBlockReasonCreate needs a window...).
But the service itself works fine.
Here some eventlog-output:
SetServiceStatus Succeed
Service started
SetServiceStatus Succeed
SERVICE_CONTROL_SHUTDOWN (<- shutdown event caught)
AbortSystemShutdown failed! Error=1115 (<- means shutdown already in progress, very funny errorcode )
The only thing left is to stop the shutdown.
On WinXP your code should work. How do you test your service?
You can just catch this event if your app really runs as service
in debug mode you will never see this event.
Here some code-changes I made (but nothing very special):
1. The "problem" that your SetServiceStatus always "fails":
void ...SetServiceStatus(DWORD dwState)
{
if (::SetServiceStatus(m_hServiceStatus, &m_status) == TRUE)
{
LogEvent(TEXT("SetServiceStatus Failed"));
}
else
{
LogEvent(TEXT("SetServiceStatus Failed"));
}
}
---> copy & paste is not always your friend.
2. In "...::Handler(...)" I made some changes to get more eventlog entries:
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
LogEvent(_T("SERVICE_CONTROL_STOP"));
break;
case SERVICE_CONTROL_PAUSE:
LogEvent(_T("SERVICE_CONTROL_PAUSE"));
break;
case SERVICE_CONTROL_CONTINUE:
LogEvent(_T("SERVICE_CONTROL_CONTINUE"));
break;
case SERVICE_CONTROL_INTERROGATE:
LogEvent(_T("SERVICE_CONTROL_INTERROGATE"));
break;
case SERVICE_CONTROL_SHUTDOWN:
LogEvent(_T("SERVICE_CONTROL_SHUTDOWN"));
AbortShutdown(chComputerName);
break;
}
3. AbortShutdown changes: (AbortShutdown is now part of your Module class, just for LogEvent)
BOOL ...::AbortShutdown(LPTSTR lpMachineName)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL fResult;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
LogEvent(TEXT("OpenProcessToken failed"));
return false;
}
if(!LookupPrivilegeValue(lpMachineName, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid))
{
LogEvent(TEXT("LookupPrivilegeValue failed"));
return false;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
{
LogEvent(TEXT("AdjustTokenPrivileges failed"));
return false;
}
LogEvent(TEXT("AbortSystemShutdown"));
fResult = AbortSystemShutdown(NULL);
if (!fResult)
{
wchar_t test[512];
swprintf((wchar_t*)&test, TEXT("AbortSystemShutdown failed! Error=%d"), (DWORD)GetLastError());
LogEvent((LPCWSTR)&test);
return false;
}
else
{
LogEvent(TEXT("AbortSystemShutdown succeed"));
}
tkp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
{
return false;
}
return true;
}
Like you see I never changed something special and your service gets the SHUTDOWN notification.
Now its just the question how to abort the shutdown? Maybe this code works on WinXP.
I would say, at first try out some more logging to the eventlog just to find out if your service
catches the event SERVICE_CONTROL_SHUTDOWN. If so then you have to find out where an error occurs.
And make sure every time you test your service really runs as service.
Let me you know what you find out, cause your code is fine.
Greetings Covean
|
|
|
|