「VBA Edge制御 更新自動化コマンドプロンプトプログラム」の版間の差分
(→概要) |
編集の要約なし |
||
(同じ利用者による、間の7版が非表示) | |||
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> | ||
50行目: | 48行目: | ||
起動引数は第1がブラウザでedge or chromeです。第2がWindowsLoginUserIDを入れます。 | |||
<yjavascript></script> | <yjavascript></script> | ||
<!-- | <!-- | ||
57行目: | 56行目: | ||
--> | --> | ||
<div class="hljs-wrap"><pre data-label="GetWebDriver.cpp" class="pre-wrap"> | <div class="hljs-wrap"><pre data-label="GetWebDriver.cpp" class="pre-wrap"> | ||
<code class="language-cpp">#include | <code class="language-cpp">#include <iostream> | ||
#include | #include <fstream> | ||
#include | #include <string> | ||
#include | #include <vector> | ||
#include | #include <filesystem> | ||
#include | #include <windows.h> | ||
#include | #include <winhttp.h> | ||
#include | #include <typeinfo> | ||
| | ||
#include | #include <zip.h> | ||
| | ||
#pragma comment(lib, "winhttp.lib") | #pragma comment(lib, "winhttp.lib") | ||
73行目: | 72行目: | ||
| | ||
std::string GetVersion(const std::string& path) { | 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) { | 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) { | 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) { | std::string GetVersionFilePath(const std::string& browser, const std::string& version) { | ||
return browser + "_" + version; | |||
} | } | ||
| | ||
bool IsVersionDownloaded(const std::string& versionFilePath) { | bool IsVersionDownloaded(const std::string& versionFilePath) { | ||
return std::filesystem::exists(versionFilePath); | |||
} | } | ||
| | ||
void SaveVersionFile(const std::string& 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) { | 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) { | 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) { | 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) { | 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[]) { | 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;</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制御 導入に戻る。