「VBA Edge制御 更新自動化コマンドプロンプトプログラム」の版間の差分
(→概要) |
編集の要約なし |
||
(同じ利用者による、間の3版が非表示) | |||
2行目: | 2行目: | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/vs2015.css"> | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/vs2015.css"> | ||
<link rel="stylesheet" href="https://wiki.yo-net.jp/custom.css"> | <link rel="stylesheet" href="https://wiki.yo-net.jp/custom.css"> | ||
<script src="https:// | <script src="https://wiki.yo-net.jp/highlight/highlight.js"></script> | ||
<script src="https://wiki.yo-net.jp/custom.js"></script> | <script src="https://wiki.yo-net.jp/custom.js"></script> | ||
<script></yjavascript> | <script></yjavascript> | ||
17行目: | 17行目: | ||
からダウンロードして解凍して、zlibはフォルダ階層のトップ下のCMakeFile.txtのあるフォルダをVisual Studioで開いて、ビルドのインストールっていうのと(zlibのパス)\out\install\x64-Debug\includeの下のzconf.hを(zlibのパス)の直下にコピーしてから、ビルドのビルドを実行するだけ。これで、zlibd.libとzlibd.dllとincludeディレクトリが生成されます。したらば次はlibzipも同じようにフォルダ階層のトップ下のCMakeFileをVisual Studioで開くんですけど、フォルダを開く前にCMakeFile.txtの中身を以下のように更新します。 | からダウンロードして解凍して、zlibはフォルダ階層のトップ下のCMakeFile.txtのあるフォルダをVisual Studioで開いて、ビルドのインストールっていうのと(zlibのパス)\out\install\x64-Debug\includeの下のzconf.hを(zlibのパス)の直下にコピーしてから、ビルドのビルドを実行するだけ。これで、zlibd.libとzlibd.dllとincludeディレクトリが生成されます。したらば次はlibzipも同じようにフォルダ階層のトップ下のCMakeFileをVisual Studioで開くんですけど、フォルダを開く前にCMakeFile.txtの中身を以下のように更新します。 | ||
<yjavascript></script> | <yjavascript></script> | ||
<!-- | <!-- | ||
26行目: | 24行目: | ||
--> | --> | ||
<div class="hljs-wrap"><pre data-label="CMakeList.txt" class="pre-wrap"> | <div class="hljs-wrap"><pre data-label="CMakeList.txt" class="pre-wrap"> | ||
<code class="language- | <code class="language-cmake">cmake_minimum_required(VERSION 3.0.2) | ||
| |||
set(ZLIB_ROOT C:/(zlibのパス)/) | set(ZLIB_ROOT C:/(zlibのパス)/) | ||
set(LIB_INCLUDE_DIR C:/(zlibのパス)/out/install/x64-Debug/include) | set(LIB_INCLUDE_DIR C:/(zlibのパス)/out/install/x64-Debug/include) | ||
set(ZLIB_LIBRARY_DEBUG C:/(zlibのパス)/out/install/x64-Debug/lib/zlibd.lib) | set(ZLIB_LIBRARY_DEBUG C:/(zlibのパス)/out/install/x64-Debug/lib/zlibd.lib) | ||
set(ZLIB_LIBRARY_RELEASE C:/(zlibのパス)/out/install/x64-Debug/lib/zlibd.lib) | set(ZLIB_LIBRARY_RELEASE C:/(zlibのパス)/out/install/x64-Debug/lib/zlibd.lib) | ||
| |||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)</code></pre><div> | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)</code></pre></div> | ||
<script></yjavascript> | <script></yjavascript> | ||
430行目: | 428行目: | ||
} | } | ||
| | ||
return 0;</code></pre><div> | return 0;</code></pre></div> | ||
<script></yjavascript> | <script></yjavascript> | ||
2025年1月12日 (日) 00:01時点における最新版
VBA Edge制御 導入に戻る。
概要
msedgedriver.exeを自動で差し替えるコマンドプロンプトプログラムをC++言語でだらだら長めのコードになりましたが、作るには作りました。クラス化とかしてません。参考にして自分で組んでみて下さい。Chromeの対応はきっちりできていません。Chromeも同じようなやり方だと思うので、Chromeのdriverも答え合わせ的に直してみるといいかもしれない。つうかzlibとlibzipのビルドとかで手間取る。古いVisualStudio17 2022とかでやるとつまづく、最新のVisualStudio17 2022に更新した上でやるとうまく行く。
からダウンロードして解凍して、zlibはフォルダ階層のトップ下のCMakeFile.txtのあるフォルダをVisual Studioで開いて、ビルドのインストールっていうのと(zlibのパス)\out\install\x64-Debug\includeの下のzconf.hを(zlibのパス)の直下にコピーしてから、ビルドのビルドを実行するだけ。これで、zlibd.libとzlibd.dllとincludeディレクトリが生成されます。したらば次はlibzipも同じようにフォルダ階層のトップ下のCMakeFileをVisual Studioで開くんですけど、フォルダを開く前にCMakeFile.txtの中身を以下のように更新します。
cmake_minimum_required(VERSION 3.0.2)
set(ZLIB_ROOT C:/(zlibのパス)/)
set(LIB_INCLUDE_DIR C:/(zlibのパス)/out/install/x64-Debug/include)
set(ZLIB_LIBRARY_DEBUG C:/(zlibのパス)/out/install/x64-Debug/lib/zlibd.lib)
set(ZLIB_LIBRARY_RELEASE C:/(zlibのパス)/out/install/x64-Debug/lib/zlibd.lib)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
その上でフォルダを開いて、インストールとビルドをするとzip.libとzip.dllとインクルードディレクトリが生成されます。したらば、このzip.dllとzlibd.libを自分で作成するプロジェクトで実行ファイル.exeが生成されるフォルダに保存するのと、インクルードディレクトリに以下の追加します。
- インクルードディレクトリ
- C:\(libzipパス)\out\install\x64-Debug\include;
- ライブラリディレクトリ
- C:\(libzipパス)\out\install\x64-Debug\lib;
そして、以下のようにコードを作成します。
起動引数は第1がブラウザでedge or chromeです。第2がWindowsLoginUserIDを入れます。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <filesystem>
#include <windows.h>
#include <winhttp.h>
#include <typeinfo>
#include <zip.h>
#pragma comment(lib, "winhttp.lib")
#pragma comment(lib, "Version.lib")
#pragma comment(lib, "zip.lib")
std::string GetVersion(const std::string& path) {
DWORD handle;
DWORD size = GetFileVersionInfoSizeA(path.c_str(), &handle);
if (size == 0) {
throw std::runtime_error("Failed to get version info size.");
}
std::vector<char> data(size);
if (!GetFileVersionInfoA(path.c_str(), handle, size, data.data())) {
throw std::runtime_error("Failed to get version info.");
}
VS_FIXEDFILEINFO* versionInfo;
UINT len;
if (!VerQueryValueA(data.data(), "\\", (LPVOID*)&versionInfo, &len)) {
throw std::runtime_error("Failed to query version info.");
}
DWORD major = (versionInfo->dwFileVersionMS >> 16) & 0xffff;
DWORD minor = versionInfo->dwFileVersionMS & 0xffff;
DWORD build = (versionInfo->dwFileVersionLS >> 16) & 0xffff;
DWORD revision = versionInfo->dwFileVersionLS & 0xffff;
return std::to_string(major) + "." +
std::to_string(minor) + "." +
std::to_string(build) + "." +
std::to_string(revision);
}
std::string GetHttpResponse(const std::wstring& host, const std::wstring& path) {
HINTERNET session = WinHttpOpen(L"Downloader", WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, NULL, NULL, 0);
if (!session) {
throw std::runtime_error("Failed to open WinHTTP session.");
}
HINTERNET connect = WinHttpConnect(session, host.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0);
if (!connect) {
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to connect to host.");
}
HINTERNET request = WinHttpOpenRequest(connect, L"GET", path.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
if (!request) {
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to open HTTP request.");
}
if (!WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) {
WinHttpCloseHandle(request);
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to send HTTP request.");
}
if (!WinHttpReceiveResponse(request, NULL)) {
WinHttpCloseHandle(request);
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to receive HTTP response.");
}
DWORD size = 0;
WinHttpQueryDataAvailable(request, &size);
std::string response(size, '\0');
DWORD downloaded;
WinHttpReadData(request, /*&response[0]*/ response.data(), size, &downloaded);
WinHttpCloseHandle(request);
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
return response;
}
void Download(const std::wstring& url, const std::string& extractDir) {
HINTERNET session = WinHttpOpen(L"Downloader", WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, NULL, NULL, 0);
URL_COMPONENTS components = { 0 };
components.dwStructSize = sizeof(URL_COMPONENTS);
components.dwHostNameLength = -1;
components.dwUrlPathLength = -1;
wchar_t host[256];
wchar_t path[1024];
components.lpszHostName = host;
components.lpszUrlPath = path;
if (!WinHttpCrackUrl(url.c_str(), 0, 0, &components)) {
throw std::runtime_error("Failed to parse URL.");
}
HINTERNET connect = WinHttpConnect(session, components.lpszHostName, INTERNET_DEFAULT_HTTPS_PORT, 0);
if (!connect) {
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to connect to host.");
}
HINTERNET request = WinHttpOpenRequest(connect, L"GET", components.lpszUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
if (!request) {
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to open HTTP request.");
}
if (!WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) {
WinHttpCloseHandle(request);
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to send HTTP request.");
}
if (!WinHttpReceiveResponse(request, NULL)) {
WinHttpCloseHandle(request);
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
throw std::runtime_error("Failed to receive HTTP response.");
}
DWORD size = 0;
WinHttpQueryDataAvailable(request, &size);
std::vector<char> data;
DWORD downloaded = 0;
do {
DWORD size = 0;
WinHttpQueryDataAvailable(request, &size);
if (size == 0) break;
std::vector<char> buffer(size);
DWORD bytesRead = 0;
if (!WinHttpReadData(request, buffer.data(), size, &bytesRead)) {
throw std::runtime_error("Failed to read HTTP response data.");
}
data.insert(data.end(), buffer.begin(), buffer.begin() + bytesRead);
downloaded += bytesRead;
} while (true);
std::filesystem::create_directory(extractDir);
std::ofstream out(extractDir + "\\driver.zip", std::ios::binary);
out.write(data.data(), downloaded);
out.close();
WinHttpCloseHandle(request);
WinHttpCloseHandle(connect);
WinHttpCloseHandle(session);
}
std::string GetVersionFilePath(const std::string& browser, const std::string& version) {
return browser + "_" + version;
}
bool IsVersionDownloaded(const std::string& versionFilePath) {
return std::filesystem::exists(versionFilePath);
}
void SaveVersionFile(const std::string& versionFilePath) {
std::ofstream file(versionFilePath);
if (file) {
file << "Downloaded";
file.close();
}
}
void extractZip(const std::string& zipPath, const std::string& extractDir) {
int zipError = 0;
// ZIPファイルを開く
zip_t* zip = zip_open(zipPath.c_str(), 0, &zipError);
if (!zip) {
std::cerr << "Failed to open ZIP file. Error code: " << zipError << std::endl;
return;
}
// エントリ数を取得
zip_int64_t num_entries = zip_get_num_entries(zip, 0);
for (zip_int64_t i = 0; i < num_entries; i++) {
// ファイル名を取得
const char* name = zip_get_name(zip, i, 0);
if (!name) {
std::cerr << "Failed to get entry name for index " << i << std::endl;
continue;
}
// ファイル名をstd::stringに変換
std::string entryName(name);
// ファイル情報を取得
zip_stat_t stat;
if (zip_stat_index(zip, i, 0, &stat) == -1) {
std::cerr << "Failed to get entry stats for " << entryName << std::endl;
continue;
}
// フルパスを作成
std::filesystem::path fullPath = std::filesystem::path(extractDir) / entryName;
// フォルダの場合、ディレクトリを作成
if (entryName.back() == '/') { // ZIP形式ではフォルダ名は末尾に'/'が付く
std::filesystem::create_directories(fullPath);
continue;
}
// ファイルを開く
zip_file_t* zf = zip_fopen_index(zip, i, 0);
if (!zf) {
std::cerr << "Failed to open file inside ZIP: " << entryName << std::endl;
continue;
}
// ファイル内容を読み込む
std::string contents(stat.size, '\0'); // std::stringでメモリ確保
if (zip_fread(zf, &contents[0], stat.size) == -1) {
std::cerr << "Failed to read file: " << entryName << std::endl;
zip_fclose(zf);
continue;
}
// 親ディレクトリを作成(必要であれば)
std::filesystem::create_directories(fullPath.parent_path());
// ファイルを保存
std::ofstream out(fullPath, std::ios::binary);
if (!out) {
std::cerr << "Failed to write file: " << fullPath << std::endl;
zip_fclose(zf);
continue;
}
out.write(contents.data(), contents.size());
out.close();
// ファイルを閉じる
zip_fclose(zf);
}
// ZIPファイルを閉じる
zip_close(zip);
}
void renameFile(const std::string& dirPath, const std::string& oldName, const std::string& newName) {
// 古いファイルのフルパス
std::filesystem::path oldFilePath = std::filesystem::path(dirPath) / oldName;
// 新しいファイルのフルパス
std::filesystem::path newFilePath = std::filesystem::path(dirPath) / newName;
try {
// ファイル名を変更
std::filesystem::rename(oldFilePath, newFilePath);
std::cout << "File renamed from " << oldFilePath << " to " << newFilePath << std::endl;
}
catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Error renaming file: " << e.what() << std::endl;
}
}
void deleteDirectory(const std::string& dirPath) {
try {
// 指定したディレクトリが存在するか確認
if (std::filesystem::exists(dirPath)) {
// 再帰的に削除
std::filesystem::remove_all(dirPath);
std::cout << "Deleted directory and contents: " << dirPath << std::endl;
}
else {
std::cerr << "Directory does not exist: " << dirPath << std::endl;
}
}
catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Error deleting directory: " << e.what() << std::endl;
}
}
void copyAndRenameFile(const std::string& sourcePath, const std::string& destPath) {
try {
// コピー先の親ディレクトリを作成(存在しない場合)
std::filesystem::create_directories(std::filesystem::path(destPath).parent_path());
// ファイルをコピー
std::filesystem::copy_file(sourcePath, destPath, std::filesystem::copy_options::overwrite_existing);
std::cout << "File copied from " << sourcePath << " to " << destPath << std::endl;
}
catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Error copying file: " << e.what() << std::endl;
}
}
int main(int argc, char* argv[]) {
if (argc < 2 || argv[1] == nullptr) {
std::cerr << "起動引数1のブラウザの種別の指定がありません。edge or chrome" << std::endl;
return 1;
}
if (argc < 3 || argv[2] == nullptr) {
std::cerr << "起動引数2のWindowsユーザ名の指定がありません。" << std::endl;
return 1;
}
std::string browser = argv[1];
std::string userId = argv[2];
std::string baseDir = "C:\\Users\\" + userId + "\\AppData\\Local\\SeleniumBasic";
std::string version;
std::wstring driverUrl;
std::string tempDir;
std::string outputPath;
try {
if (browser == "chrome") {
version = GetVersion("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe");
std::wstring driverUrl = L"https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_" + std::wstring(version.begin(), version.end());
tempDir = "chromedriver_temp";
outputPath = baseDir + "\\chromedriver.exe";
//DownloadAndExtract(driverUrl, tempDir, baseDir + "\\chromedriver.exe");
}
else if (browser == "edge") {
version = GetVersion("C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe");
driverUrl = L"https://msedgedriver.azureedge.net/" + std::wstring(version.begin(), version.end()) + L"/edgedriver_win64.zip";
tempDir = "edgedriver_temp";
outputPath = baseDir + "\\edgedriver.exe";
//DownloadAndExtract(driverUrl, tempDir, baseDir + "\\edgedriver.exe", "msedgedriver.exe");
}
else {
std::cerr << "Unsupported browser: edge or chrome" << browser << std::endl;
return 1;
}
std::string versionFilePath = GetVersionFilePath(browser, version);
if (IsVersionDownloaded(versionFilePath)) {
std::cout << "Version " << version << " is already downloaded. Skipping download." << std::endl;
}
else {
Download(driverUrl, tempDir);
std::cout << "Download and extraction complete for version: " << version << std::endl;
SaveVersionFile(versionFilePath);
std::string zipPath;
std::string FixFilename;
std::string driverDir;
zipPath = tempDir + "\\driver.zip";
driverDir = tempDir + "\\driver";
extractZip(zipPath, driverDir);
copyAndRenameFile(driverDir + (browser == "edge" ? "\\msedgedriver.exe" : "\\chromedriver.exe"), outputPath);
FixFilename = browser + "driver_" + std::string(version.begin(), version.end()) + ".zip";
renameFile(tempDir, "driver.zip", FixFilename);
deleteDirectory(driverDir);
}
}
catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
return 1;
}
return 0;
VBA Edge制御 導入に戻る。