EntryNavi : « 馬車道のチーズケーキ | メイン | ペコちゃんのほっぺアイス イチゴミルク »

CategoryNavi : メイン -> コンピューター -> 開発 -> C/C++

リモートのWindows PCをシャットダウンする

LAN上にいる他のWindowsマシンを再起動・シャットダウンする方法。
NT系だと権限ってのがありますので少々めんどくさいです。
流れは下記の通りです。
  • IPC$という共有リソースへアクセスすることでリモートマシンへログオンする。
    WNetAddConnection2()を使用します。
  • SE_REMOTE_SHUTDOWN_NAME権限を取得する。
    OpenProcessToken()
    LookupPrivilegeValue()
    AdjustTokenPrivileges()
    を使用します。
  • シャットダウン指示を出します。
    InitiateSystemShutdownEx()を使用します。
    AbortSystemShutdown()を使用すると逆に中断させれます。
  • SE_REMOTE_SHUTDOWN_NAME権限を解除する。
  • ログオフする。
    WNetCancelConnection2()を使用する。
以上のような感じです。
自分自身をシャットダウンする場合は、ログオン作業を行わずにユーザー名とパスワードをNULLにして 実行すると行えます。
シャットダウン前にカウントダウンをさせることが出来ます。 また、カウントダウン中に限って中断させることが出来ます。

InitiateSystemShutdownEx()の引数でbForceAppsClosed=trueに指定すると、変更された内容のあるアプリに 確認ダイアログを出させることなく強制的に終了させることが出来ます。
これは、ウインドウをロックしていても有効です。逆に言うとロックされていると通常は落とせない 事になります。
この値をtrueにして強制的に落とさないとエラー番号[0x555]が返されてシャットダウンできません。
ExitWindowsEx()というAPIを使用するとローカルマシン(自分自身)のみですが、ログオフ・再起動・シャットダウン・電源切断の4種類から選ぶことが出来て少し細かい操作が出来ます。というか、自分だけでよければこちらを使うべきでしょう。
ExitWindowsExの場合は、SE_SHUTDOWN_NAME権限が必要になりますのでご注意ください。

InitiateSystemShutdownExは、9x系とNTは使用できませんのでご注意ください。2000 / XP 以降のみです。

いつもの通りサンプルです。
#include <stdio.h>
#include <windows.h>

bool RemoteShutdown(char *server_name,char *user_name,char *user_pass
,char *count_down_msg,DWORD count_down_time
,bool force_close,bool reboot,bool abort);
bool AccessPrivilege( char *prvlg,char *server_name, bool mode);
bool LogonRemoteComputer(char *server_name,char *user_name,char *password);
bool LogoffRemoteComputer(char *server_name);

int main(int argc,char *argv[])
{
RemoteShutdown("\\\\host_name","user","pass"
,"テストプログラムからです。",260,true,true,false);

return 0;
}

bool RemoteShutdown(char *server_name,char *user_name,char *user_pass
,char *count_down_msg,DWORD count_down_time
,bool force_close,bool reboot,bool abort)
{
bool ret;

if(user_name != NULL){
if(!LogonRemoteComputer(server_name,user_name,user_pass)){
printf("ログオンエラー\n");
return false;
}
}

if(!AccessPrivilege(SE_REMOTE_SHUTDOWN_NAME,server_name,true)){
printf("特権を取得できません。\n ");
ret = false;
}else{
if(!abort){
//通常シャットダウン
if(InitiateSystemShutdownEx(server_name,count_down_msg,count_down_time
,force_close,reboot,0xffff)){
printf("%d秒後に%sのシャットダウンを開始します。\n",count_down_time,server_name);
}else{
printf("%sのシャットダウンに失敗しました。\n",server_name);
ret = false;
}
}else{
//シャットダウンの停止
if(AbortSystemShutdown(server_name)){
printf("%sのシャットダウンを中断しました。\n",server_name);
}else{
printf("%sのシャットダウンの中断に失敗しました。\n",server_name);
ret = false;
}
}
if(!AccessPrivilege(SE_REMOTE_SHUTDOWN_NAME,server_name,false)){
printf("特権を戻せません。");
ret = false;
}
}

if(user_name != NULL){
if(!LogoffRemoteComputer(server_name)){
printf("ログアウトエラー\n");
ret = false;
}
}

return ret;
}
/////////////////////////////////////////////////////////////////////////////
// 特権をコントロールする
bool AccessPrivilege( char *privilege_value,char *server_name, bool mode)
{
HANDLE token;
LUID luid;
TOKEN_PRIVILEGES tokenPrivileges;

if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&token)){
return false;
}

if(!LookupPrivilegeValue(server_name,privilege_value,&luid)){
return false;
}

tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luid;

if(mode){
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
}else{
tokenPrivileges.Privileges[0].Attributes = 0;
}

if(!AdjustTokenPrivileges(token,false,&tokenPrivileges,sizeof(TOKEN_PRIVILEGES),0,0)){
return false;
}
if(GetLastError() != ERROR_SUCCESS){
return false;
}

return true;
}
/////////////////////////////////////////////////////////////////////////////
// リモートコンピュータにログオン
bool LogonRemoteComputer(char *server_name,char *user_name,char *password)
{
NETRESOURCE NetRes;
char str[MAX_PATH];
bool ret = true;

memset( str, 0, sizeof(str));
memset( &NetRes, 0, sizeof(NetRes));

NetRes.dwType = RESOURCETYPE_DISK;

lstrcpyn( str, server_name, sizeof(str));
strcat( str, "\\IPC$" );
NetRes.lpRemoteName = str;

DWORD retn = WNetAddConnection2(&NetRes,password,user_name,CONNECT_UPDATE_PROFILE );

if(retn != NO_ERROR){
ret = false;
}

return ret;
}
/////////////////////////////////////////////////////////////////////////////
// リモートコンピューからログオフ
bool LogoffRemoteComputer(char *server_name)
{
char str[MAX_PATH];
bool ret = true;

memset( str, 0, sizeof(str));

lstrcpyn( str, server_name, sizeof(str));
strcat( str, "\\IPC$" );
DWORD retn = WNetCancelConnection2( str, CONNECT_UPDATE_PROFILE, false );

if(retn != NO_ERROR){
ret = false;
}

return ret;
}
<Category : C/C++>

検索

Google

サイドフィード

track feed 理ろぐ
人気ブログランキング - 理ろぐ
Powered by
Movable Type 3.34