エマルのプログラミング備忘録

だいたい付箋。一口サイズのメモ帳

C++ 環境変数を含むパスをstd::stringに展開する方法

はじめに

パスに限らず、環境変数を含む文字列は、
WindowsAPIの ExpandEnvironmentStrings で展開できます。
std::string に展開する方法をメモ。

実装

あとがき

今回は、stringに展開しましたが、
wstring なら ExpandEnvironmentStringsW で展開できます。

ファイルエクスプローラーからコマンドプロンプトを起動するテクニックの罠

f:id:inemaru:20180226213203p:plain

はじめに

ファイルエクスプローラー使用時に、
現在のディレクトリをカレントとしてコマンドプロンプトを起動するテクニックとして
アドレスバーに「cmd」と入力する方法が紹介されることがあります。

このテクニックが、意図通り動作しないことがあるという話。

そもそも、なぜコマンドプロンプトが起動するのか

動作原理は、下記の通り。

  • 環境パスが設定されている場所に、cmd.exe がある
  • 拡張子の.exe は、省略ができる
  • ファイルエクスプローラーのアドレスバーは、現在のディレクトリをカレントとしてコマンドを受け付ける

問題とその対処

問題

環境パスが通っている場所(例えば、デスクトップ)に「cmd」というフォルダあったとします。
この状態で、先に説明したテクニックを使用するとコマンドプロンプトは起動しません。

デスクトップの「cmd」フォルダが開くことになります。
これは、拡張子をつけても同じ話で「cmd.exe」と言う名前でフォルダがあれば同様の挙動となります。

対処法

「cmd」を「%ComSpec%」とすれば、解決します。

環境変数を使用する事で、
コマンドプロンプトの実行ファイルをフルパスで指定するため、問題は回避できます。

あとがき

このテクニックは、うまく動作する場合の方が多いので、
説明が省かれることが多いと思い、備忘録行き。

C++ で、コマンドの標準出力を取得する方法(CreateProcessなし)

はじめに

Windows でコマンドを実行する際、標準出力を取得する方法です。
コンソール画面が表示されても問題ない場合、
もしくは、CUIプログラムで使用できる方法です。

前提

system 関数だけでは、標準出力が簡単に取得できません。
Windows 環境では、APIの CreateProcess を使用する方法が良く使用されますが、
Linux 環境などで使用される popen を使用した方がシンプルに実装できます。

標準エラーの対応は、行っていませんが、
表示したくない場合は、実行コマンド末尾に「 2>&1」を付けて標準出力にリダイレクトする等
適宜対応しましょう。

実装

あとがき

Windows では、popen が使用できないと思い込んでいましたが、
_popen の名前で、使用できるので、実装して備忘録行き。

WSH JScript をバッチに埋め込んだ際にコンソールウィンドウのPIDを取得する方法

はじめに

タイトルの通り、バッチファイルからWSH(cscript)を起動した際に
コンソールウィンドウのPIDを取得する方法です。

概要

WSHからアプリケーションを実行中に
コンソールウィンドウが閉じられると困るので、
コンソールウィンドウのプロセスを特定するために使用します。

実装

あとがき

JScript から C# を実行するときに
コンソールウィンドウの表示状態を操作するために使う実装です。
ニッチすぎるネタ。

【WSH】JScript で、多重起動判定

はじめに

WSHで多重起動判定する方法です。
できるだけ、スマートに実装したつもりです。

実装

サンプルは、shebang記法でバッチファイルにJScriptに埋め込みしていますが
普通に.jsでも動くはず。
Sleepで適当な時間待って、終了前に起動したものは多重起動判定されます。

判定方法は、WMIを使用して、実行ファイル名で検索をかけることで実現しています。
そのため、同名のバッチファイルが起動されていると誤検出し得るので、
ファイル名は、被らないようにしましょう。

あとがき

そこまで凝ったモノは要らない人向けです。
簡単な物であれば、5行程度で判定できるというネタでした。


C++ コマンドライン引数をstd::vector<std::string>に展開する方法

ちょっとしたメモ

コマンドライン引数をstd::vector<std::string>に展開する方法です。
パース自体は、コンストラクタのみで実現できます。

実装

あとがき

エントリーポイントを int main(std::vector<std::string> args)
みたいに書けたら楽ですが、そういう横着はできません。

元ネタは、下記を参照。
stackoverflow.com