WindowsからDOS窓を見せないようにするには?

解決


ぱみゅ  2013-11-22 03:13:59  No: 45611

開発環境はWindowsXP/7とDelphi6です。
今作っているプログラムでどうしてもDOSのコマンドラインから
実行しなければならないプロセスがあります。
普通にやるとけっこう大きなDOS窓が出て、不格好です。
DOS窓を出さない、画面外に出す、極めて目立たない
小さな状態で出すなど、なにか良い方法はないでしょうか?


Mr.XRAY  2013-11-22 04:49:23  No: 45612

>DOS窓を出さない、

現在はどのようなコードで,どのようなプログラムを実行しているのでしょうか ?

(1) 現在の方法を使用して,コマンドプロンプトを表示しないように修正する
(2) コマンドプロンプトが表示しないようにできるのであれば,他の方法でもよい

備考
WindowsXP/7 には DOS 窓というのはありません.
おそらくコマンドプロンプトのことだと思います.

>DOSのコマンドラインから実行しなければならないプロセスがあります。
>(改行位置を変更しました)

ということは,現在は,コマンドプロンプトを起動して,そこにコマンドを入力して
実行している,ということでしょうか ?


ぱみゅ  2013-11-22 06:14:45  No: 45613

Mr.XRAYさん、さっそくのレスポンスありがとうございます。
具体的に起動したいのはuudx.exeです。

> 現在は,コマンドプロンプトを起動して,そこにコマンドを入力して
> 実行している,ということでしょうか ?

起動するコードは下記のようにしています。

procedure TForm1.Button1Click(Sender: TObject);
var
  res : boolean;
  Si  : TStartupInfo;
  Pi  : TProcessInformation;

begin
  GetStartupInfo(Si);
  res := CreateProcess(nil,
                    PChar('uudx.exe'),
                    nil,
                    nil,
                    False,
                    CREATE_DEFAULT_ERROR_MODE,
                    nil,
                    nil,
                    SI,
                    PI);
  if res = false then MessageDlg('ソフトの起動に失敗しました。',mtError,[mbOk],0);
end;


deldel  2013-11-22 17:53:29  No: 45614

例えば、こんなコードはどうでしょうか?
Win7,D6では動作しました。
ただ、Win7,XE4ではエラーが出ました。

var
  cmd: string;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb := SizeOf(TStartupInfo);

  //コマンドプロンプトウィンドウを非表示に
  StartupInfo.dwFlags := StartF_UseShowWindow;
  StartupInfo.wShowWindow := SW_Hide;

  //DOSのTreeコマンドを実行
  cmd := 'command.com /c tree c:\temp > c:\tree.txt';

  if CreateProcess(nil,
                   PChar(cmd),
                   nil,
                   nil,
                   False,
                   0,
                   nil,
                   'c:\',
                   StartupInfo,
                   ProcessInfo) then begin
      WaitForSingleObject(ProcessInfo.hProcess, Infinite);
      CloseHandle(ProcessInfo.hProcess);
  end;
end;


ぱみゅ  2013-11-23 03:03:14  No: 45615

deldelさん、具体的なコードを提示していただいて
ありがとうござます。今日さっそく書き換えたところ、
想定していた通りの動作になりました。
これは今後も便利そうなので、汎用で使える関数や手続きをまとめた
自分のライブラリィにインプリメントしておくことにしました。
重ねてお礼申し上げます。


ぱみゅ  2013-11-23 20:30:10  No: 45616

> ただ、Win7,XE4ではエラーが出ました。

Windows7,Delphi6でも正常な動作を確認しました。
ありがとうございました。


Mr.XRAY  2013-11-24 09:23:23  No: 45617

>ただ、Win7,XE4ではエラーが出ました。

以下のようにしてみてください.

  //参照カウンタ対策
  UniqueString(Cmd);   // これを追加
  if CreateProcess(nil,
  
  以下,省略


Mr.XRAY  2013-11-24 09:34:15  No: 45618

>command.com

ついでに,参考までに,Windows Vista, Windows 7 の 64 ビット版では,
Command.com はなくなりました.
Cmd.exe を使用することになります.


deldel  2013-11-25 18:10:34  No: 45619

Mr.XRAYさん、ありがとうございます。
UniqueString(Cmd);を追加すると正常に処理できました。

この関数は初めて見たのですが、XEでは、PChar(cmd) などを行う前に
UniqueString(Cmd) を行ったほうがいいということなのでしょうか?


Mr.XRAY  2013-11-26 03:09:21  No: 45620

これは「参照カウンタ」の問題ですね.
ということは「参照カウンタ」のことを書かないと,ということなのですが.
ググッていただくのがいいと思うのですが,ググったら,あまりいいのがないですね.

というこで,参照カウンタについて説明を書き始めたのですが,長くなってしまいました (笑)
そこで,その説明はやめて,とりあえず以下を参考にしてください.
今回は,ユニコード版の CreateProcess の問題です.

[Delphi Unicodeワールド パートIII: コードをUnicode対応にする]
http://edn.embarcadero.com/jp/article/38699

ページ内を CreateProcess で検索

[各種文字列の実際]
http://ht-deko.minim.ne.jp/tech018.html

[デバッグ時に CreateProcess() や ShellExecute() でおかしくなる。 (Unicode 版 Delphi)]
http://ht-deko.minim.ne.jp/tech050.html

参照カウンタについて一番明確なのが,COM のインターフェイスを使用する時です.
AddRef (インクリメント.Ref は参照の意味でしょう)
Release (デクリメント.解放です)

C++ では明示的にこのメソッドの処理コードを書くことになります.
Delphi では,これを意識しなくても自動でやってくれます.
余談ですが,Delphi 2010 は一部のインターフェイスで,問題があって,
以下のページのコードでは,自前でやりました.
興味があったらページ内を「参照カウンタ」で検索してみてください.
本当は,継承元の AddRef, Release を実行すればいいのですが,チョンボしています.

http://mrxray.on.coocan.jp/Delphi/plSamples/947_ExplorerBrowsert.htm

# レスにも体力が必要ですな.ハハハッ.


Mr.XRAY  2013-11-26 03:20:58  No: 45621

>本当は,継承元の AddRef, Release を実行すればいいのですが,チョンボしています.

何故 -1 にしているのかは,

[各種文字列の実際]
http://ht-deko.minim.ne.jp/tech018.html

を参考にしてください.
「文字列」というオブジェクトも「COM インターフェイス」のオブジェクトも扱いは同じです.
「参照カウンタ」という数ですから.


Protect  2013-11-26 03:48:22  No: 45622

>「参照カウンタ」の問題
というのは違います。
「参照カウンタ」は間接的には関係していますが、原因ではありません。

CreateProcessWは一部の引数に書き込み権限を要求します。
しかし定数や参照カウンタが-1の文字列が置かれているメモリ領域は読み込み専用となっています。
このためアクセス違反が出るのです。

試しに文字列定数を変数に代入し、System.pas内にあるPStrRecでキャストする等して
参照カウントを書き換えてみると分かりますが、ここは関係していません。
あくまでも元の文字列が置かれた領域のアクセス保護如何によるので、
VirtualProtectを利用して書き込み権限を与えても正しく動作するようになります。


Mr.XRAY  2013-11-26 04:03:43  No: 45623

>しかし定数や参照カウンタが-1の文字列が置かれているメモリ領域は読み込み専用となっています。
>このためアクセス違反が出るのです。

フォローありがとうございます.

>VirtualProtectを利用して書き込み権限を与えても正しく動作するようになります。

こちらの方がよさそうですね.


deldel  2013-11-27 17:50:45  No: 45624

Mr.XRAYさん、Protectさん、ありがとうございます。
10年以上Delphi使ってますが、参照カウンタ、全く知らずに
今に至っています(^^;
正直、初耳で大変参考になりました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加