C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: カスタムアクションからタスクスケジューラーを追加したい


(過去ログ 136 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■80259 / inTopicNo.1)  カスタムアクションからタスクスケジューラーを追加したい
  
□投稿者/ アブサン (6回)-(2016/06/24(Fri) 17:55:54)

分類:[C/C++] 

元々のやりたいことはログイン時に管理者権限でEXEを起動したいのですが
スタートアップフォルダにいれても起動できないのでタスクスケジューラー
から起動することにしました。

そこでセットアップからタスクスケジューラーに追加したいと思い
カスタムアクション(C++)で下記処理をいれました。

最後までエラーにならず通るものの、タスクスケジューラの一覧に追加されません。
試しに手動で同名のタスクを追加したところ追加できてしまう状態です。
つまり、見えてないのではなく、追加されていないのだと思います。

ちなみにOrcaでmsiを確認するとCustomActionテーブルのTypeには「3073」が
入っているので管理者権限としてカスタムアクションは動いていると
思うのですが…。

何が悪いのかわからずに困っている状況です。
アドバイスをいただけると助かります。
よろしくお願いいたします。

#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>

static BOOL CreateSchTask(CString execPath)
{
	HRESULT hr = ERROR_SUCCESS;
	ITaskScheduler *pITS;
	hr = CoInitialize(NULL);
	if (SUCCEEDED(hr))
	{
		hr = CoCreateInstance(CLSID_CTaskScheduler,
				NULL,
				CLSCTX_INPROC_SERVER,
				IID_ITaskScheduler,
				(void **) &pITS);
		if (FAILED(hr))
		{
			CoUninitialize();
			return FALSE;
		}
	}
	else
	{
		return FALSE;
	}

	//タスク作成
	LPCWSTR pwszTaskName;
	pwszTaskName = L"StartupTest";
	ITask *pITask;
	hr = pITS->NewWorkItem(pwszTaskName, CLSID_CTask, IID_ITask, (IUnknown**)&pITask);
	pITS->Release();
	if (FAILED(hr))
	{
		CoUninitialize();
		return FALSE;
	}

	//実行プログラム設定
    pITask->SetApplicationName(execPath);

	//トリガー作成
	ITaskTrigger* pITaskTrig = NULL;
	WORD wTrigNumber = 0;
	hr = pITask->CreateTrigger(&wTrigNumber, &pITaskTrig);
	if (FAILED(hr))
	{
		pITask->Release();
		CoUninitialize();
		return FALSE;
	}

	//スケジュール設定
	TASK_TRIGGER rTrigger;
	ZeroMemory(&rTrigger, sizeof(TASK_TRIGGER));
	rTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
	rTrigger.TriggerType = TASK_EVENT_TRIGGER_AT_LOGON;
	rTrigger.wBeginYear = 2004;
	rTrigger.wBeginMonth = 4;
	rTrigger.wBeginDay = 10;
	rTrigger.wStartHour = 10;
	rTrigger.wStartMinute = 0;	
	hr = pITaskTrig->SetTrigger(&rTrigger);
	pITaskTrig->Release();
	if (FAILED(hr))
	{
		pITask->Release();
		CoUninitialize();
		return FALSE;
	}

	IPersistFile *pIPersistFile = NULL;
	hr = pITask->QueryInterface(IID_IPersistFile,
                              (void **)&pIPersistFile);
	pITask->Release();
	if (FAILED(hr))
	{
		CoUninitialize();
		return FALSE;
	}

	hr = pIPersistFile->Save(NULL, FALSE);
	pIPersistFile->Release();
	if (FAILED(hr))
	{
		CoUninitialize();
		return FALSE;
	}
  
	CoUninitialize();
	return TRUE;
}

引用返信 編集キー/
■80260 / inTopicNo.2)  Re[1]: カスタムアクションからタスクスケジューラーを追加したい
□投稿者/ アブサン (7回)-(2016/06/24(Fri) 18:02:35)
バージョンを書き忘れました

VS2008のセットアッププロジェクトでMSIを作成
VS2008のC++でカスタムアクションを作成
テスト環境はWindows7 64bit

セットアップ、カスタムアクションは32bitで作成してますが
関係あるでしょうか??

引用返信 編集キー/
■80279 / inTopicNo.3)  Re[1]: カスタムアクションからタスクスケジューラーを追加したい
□投稿者/ とっちゃん (378回)-(2016/06/27(Mon) 10:53:55)
No80259 (アブサン さん) に返信
> 元々のやりたいことはログイン時に管理者権限でEXEを起動したいのですが
> スタートアップフォルダにいれても起動できないのでタスクスケジューラー
> から起動することにしました。
>
これは、OSの仕様です。管理者権限を持つ(起動時に昇格を要求する)プログラムは
スタートアップから直接呼び出せないようになりました。

タスクスケジューラを経由するくらいならちゃんとしたサービスを作ったほうが
いいと思います。


> そこでセットアップからタスクスケジューラーに追加したいと思い
> カスタムアクション(C++)で下記処理をいれました。
>
> 最後までエラーにならず通るものの、タスクスケジューラの一覧に追加されません。
> 試しに手動で同名のタスクを追加したところ追加できてしまう状態です。
> つまり、見えてないのではなく、追加されていないのだと思います。
>
> ちなみにOrcaでmsiを確認するとCustomActionテーブルのTypeには「3073」が
> 入っているので管理者権限としてカスタムアクションは動いていると
> 思うのですが…。
>
> 何が悪いのかわからずに困っている状況です。
> アドバイスをいただけると助かります。
> よろしくお願いいたします。
>

ソースコードを吟味したわけではありませんが、
CoInitialize() はいりません。既に初期化済みです(STAで初期化されています)。

もし、CoInitialize()を呼び出す処理を入れるなら、
hr = CoInitialize();
のあと、この hr はとっておき、
CoUninitialize() を無条件で呼び出さずに

if( hr == S_OK ) CoUninitialize();

とする必要があります。CoInitialize() は、S_FALSE で成功を返す(既にSTAで初期化済みを意味する)場合があります。


そのほかは、ぱっと見ではわかりませんね。
各種メソッドの戻り値をログに出力してみるとか、デバッガでチェックするなど、細かく調査しないとわからないです。

!FAILED(==SUCCEEDED) も、S_OK と S_FALSE の2種類があります。メソッドによっては意味を持って S_FALSE を返す場合があります。
そのあたりもきちんと調査してみる必要があるかもしれません。

ところで、この関数は普通のプログラムから呼び出した場合(もちろん管理者モードで実行)は成功するのでしょうか?
ここを見てる限り、execPath 以外はインストーラの影響を受ける部分はないように思います。

引用返信 編集キー/
■80282 / inTopicNo.4)  Re[2]: カスタムアクションからタスクスケジューラーを追加したい
□投稿者/ アブサン (8回)-(2016/06/27(Mon) 12:35:36)
No80279 (とっちゃん さん) に返信

ご返信いただきありがとうございます。

試しにアカウント情報を設定したところタスクスケジューラーに追加されました。
pITask->SetAccountInformation(L"TEST", L"");

手動でタスクスケジューラーを追加すると特に設定しなくともログインユーザーのアカウントが
入っているようですが、プログラムから追加する際は明示的にアカウント情報の設定が必要なの
だろうか?

パスワードも必要なのでできれば省略したいところなのですが、仕方がないのでダイアログを
表示してユーザーにいれていただくようにしようと思います。

ちなみに execPath の内容ですが、これが影響しているかもしれないと思い、現状 「cmd.exe」
で確認していました。

また、ご指摘いただきた箇所は別途調査および見直しを行います。
いつも とっちゃん様にはお世話になり感謝しております。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -