外部プログラムとして起動する試み
以前の記事(割と初期)でC++ Builder CEで使えるPopenを開発紹介しました。
これを使うことも可能ですが、純粋にCreateProcessを使う方法を取りました。Popenではcmd.exeを通すことによりcode pageの影響を受けることになり、日本語を含むフルパスで文字化けによるエラーがでることがわかったからです。いきなりバルクで試してもいいのですが、まずは単一ファイルでトライしてみましょう。動いているプログラムのソースコード等を紹介します。まずフォームから、

Drag and Dropに前述の仕組みを使う関係で珍しくFMXです。上図のように、TLabelを2個、TButtonを1個、TOpenDialogを1個使います。配置は適当でいいのですが、Label1は幅を長く取るのが吉です。続いて、Unit1.h
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.Dialogs.hpp>
#include <FMX.StdCtrls.hpp>
#include <FMX.Types.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TOpenDialog *OpenDialog1;
TButton *Go;
TLabel *Label1;
TLabel *Label2;
void __fastcall GoClick(TObject *Sender);
private: // ユーザー宣言
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endifさらにUnit1.cpp
//---------------------------------------------------------------------------
#include <fmx.h>
#pragma hdrstop
#include <windows.h>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
bool CreateProcess(String cmdline)
{
STARTUPINFOW si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
// 実行ファイルと引数(1つの文字列にまとめる)
//wchar_t cmdLine[] = L"notepad.exe C:\\Temp\\test.txt";
if (CreateProcessW(
NULL, // 実行ファイル名(NULLなら cmdLine から取得)
cmdline.w_str(), // コマンドライン
NULL, // プロセスセキュリティ属性
NULL, // スレッドセキュリティ属性
FALSE, // ハンドル継承
0, // 作成フラグ
NULL, // 環境変数
NULL, // カレントディレクトリ
&si, // STARTUPINFO
&pi // PROCESS_INFORMATION
)) {
// プロセス終了を待つ場合
//WaitForSingleObject(pi.hProcess, INFINITE);
// ハンドルを閉じる
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
} else {
ShowMessage(L"CreateProcess に失敗しました。");
return false;
}
}
void ProcessFile(String fname)
{
String comm = "c:\\program files\\python311\\exiv2.exe";
comm += " -k -d e ";
comm += "\"" + fname + "\"";
Form1->Label1->Text = comm;
if( CreateProcess(comm) )
Form1->Label2->Text = "success";
else
Form1->Label2->Text = "failed";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::GoClick(TObject *Sender)
{
if( OpenDialog1->Execute())
ProcessFile(OpenDialog1->FileName);
}
//---------------------------------------------------------------------------Build and Runすると、

“Go”ボタンをクリックすると、

こんなファイル選択ダイアログが出ます。アイコン表示してるので画像を選択しやすいですね。で、IMG_0503.JPGを選ぶと、

となり、successですからExif情報が削除できているはずです。ファイルを選択して、プロパティーで確認すると、

ごっそり削除されています。これでおけですね。他にExifToolというのもあります。こちらはPerlで書かれたものだというので敬遠したんですが、C++から呼び出せるかも
というのでこちらの方が柔軟に使えるかもしれませんね。ま、これいじるくらいなら、自前でExifデータの中からGPS関連のデータだけ削除すればいいんですが、そのうち実現するかもしれません。webサイトならありますね。
Exiv2使ってExif情報まるごと削除すると予想外の副作用が出るんですけど、それは別記事で。


コメント