Saya tahu pertanyaan ini telah ditanyakan sebelumnya tetapi saya masih belum melihat jawaban yang memuaskan, atau jawaban yang pasti "tidak, ini tidak dapat dilakukan", jadi saya akan bertanya lagi!
Yang ingin saya lakukan adalah mendapatkan jalur ke eksekusi yang sedang berjalan, baik sebagai jalur absolut atau relatif ke tempat eksekusi dipanggil, dengan cara yang tidak bergantung platform. Saya pikir boost :: filesystem :: initial_path adalah jawaban untuk masalah saya tetapi tampaknya hanya menangani bagian 'platform-independen' dari pertanyaan - ia masih mengembalikan jalur tempat aplikasi dipanggil.
Untuk sedikit latar belakang, ini adalah game yang menggunakan Ogre, yang saya coba buat profilnya menggunakan Very Sleepy, yang menjalankan target yang dapat dieksekusi dari direktorinya sendiri, jadi tentu saja saat memuat game tidak menemukan file konfigurasi, dll. Dan segera crash . Saya ingin dapat memberikan jalur absolut ke file konfigurasi, yang saya tahu akan selalu ada di samping file yang dapat dieksekusi. Hal yang sama berlaku untuk debugging di Visual Studio - Saya ingin dapat menjalankan $ (TargetPath) tanpa harus mengatur direktori kerja.
sumber
Jawaban:
Tidak ada cara lintas platform yang saya tahu.
Untuk Linux: readlink / proc / self / exe
Windows: GetModuleFileName
sumber
Fungsi boost :: dll :: program_location adalah salah satu metode lintas platform terbaik untuk mendapatkan jalur eksekusi yang dapat dijalankan yang saya ketahui. Pustaka DLL telah ditambahkan ke Boost dalam versi 1.61.0.
Berikut ini adalah solusi saya. Saya telah mengujinya di Windows, Mac OS X, Solaris, Free BSD, dan GNU / Linux.
Ini membutuhkan Boost 1.55.0 atau lebih tinggi. Ia menggunakan perpustakaan Boost.Filesystem langsung dan Boost.Locale perpustakaan dan Boost.System perpustakaan secara tidak langsung.
src / executable_path.cpp
src / detail / executable_path_internals.cpp
sertakan / boost / executable_path.hpp
sertakan / boost / detail / executable_path_internals.hpp
Saya memiliki proyek yang lengkap, termasuk aplikasi pengujian dan file build CMake yang tersedia di SnKOpen - / cpp / executable_path / trunk . Versi ini lebih lengkap dari versi yang saya berikan di sini. Ini juga mendukung lebih banyak platform.
Saya telah menguji aplikasi pada semua sistem operasi yang didukung dalam empat skenario berikut.
Dalam keempat skenario, fungsi executable_path dan executable_path_fallback berfungsi dan mengembalikan hasil yang sama.
Catatan
Ini adalah jawaban terbaru untuk pertanyaan ini. Saya memperbarui jawaban untuk mempertimbangkan komentar dan saran pengguna. Saya juga menambahkan link ke sebuah proyek di SVN Repository saya.
sumber
argv[0]
bisa juga berupa nama yang dapat dieksekusi, dalam hal ini perlu mencarinya diPATH
sistem * nix.Cara ini menggunakan boost + argv. Anda menyebutkan ini mungkin bukan lintas platform karena mungkin atau mungkin tidak termasuk nama yang dapat dieksekusi. Nah kode berikut harus mengatasi itu.
Kode berikut mendapatkan direktori kerja saat ini yang dapat melakukan apa yang Anda butuhkan
Catatan Baru menyadari bahwa
basename(
) sudah usang jadi harus beralih ke.stem()
sumber
.parent_path()
, bukan.stem()
?@Claudiu
dikatakan, saya pikir seharusnya begitu.parent_path()
.Saya tidak yakin tentang Linux, tetapi coba ini untuk Windows:
sumber
WCHAR ownPth..
, melingkari a#ifdef UNICODE
jika dikompilasi dengan dukungan Unicode. Jika tidak, gunakan kode yang tersedia.HMODULE hModule = GetModuleHandle(NULL);
Untuk windows:
GetModuleFileName
- mengembalikan jalur exe + nama file exeUntuk menghapus nama file
PathRemoveFileSpec
sumber
This function is deprecated. We recommend the use of the PathCchRemoveFileSpec function in its place
.C ++ 17, windows, unicode, menggunakan api baru sistem file:
Dugaan solusi ini harus portabel, tetapi tidak tahu bagaimana unicode diimplementasikan pada OS lain.
weakly_canonical diperlukan hanya jika Anda menggunakan sebagai referensi folder atas Direktori Output ('..') untuk menyederhanakan jalur. Jika Anda tidak menggunakannya - hapus.
Jika Anda beroperasi dari pustaka tautan dinamis (.dll /.so), maka Anda mungkin tidak memiliki argv, maka Anda dapat mempertimbangkan solusi berikut:
application.h:
application.cpp:
sumber
QT menyediakan ini dengan abstraksi OS sebagai QCoreApplication :: applicationDirPath ()
sumber
QCoreApplication::applicationDirPath: Please instantiate the QApplication object first
. Ada ide bagaimana mengatasinya?QCoreApplication
seperti ituQApplication application(argc, argv);
(lakukan ini di Andamain(argc, argv)
, dan pastikan Anda tidak memodifikasiargc/argv
, karena ini harus tetap valid selama masa pakai QCoreApplication (periksa dokumentasi )Ini adalah cara khusus Windows, tetapi setidaknya setengah dari jawaban Anda.
GetThisPath.h
GetThisPath.cpp
mainProgram.cpp
Saya akan menyarankan menggunakan deteksi platform sebagai arahan preprocessor untuk mengubah implementasi fungsi pembungkus yang memanggil
GetThisPath
setiap platform.sumber
Menggunakan args [0] dan mencari '/' (atau '\\'):
DIEDIT: Jika '/' tidak ada, pos == - 1 jadi hasilnya benar.
sumber
args[0]
mungkin sebenarnya bukan jalur sama sekali.args[0]
tidak selalu menjadi jalur yang dapat dieksekusi yang mengganggu saya. Terima kasih telah memperbaiki jawaban Anda untuk Windows :)Untuk Windows, Anda dapat menggunakan GetModuleFilename ().
Untuk Linux, lihat
mirror BinReloc (URL lama, tidak berfungsi)dari BinReloc di repositori GitHub datenwolf .sumber
Berikut ini berfungsi sebagai solusi cepat dan kotor, tetapi perlu diperhatikan bahwa ini jauh dari kata mudah:
sumber
Jika Anda perlu menangani jalur unicode untuk Windows:
sumber
Untuk Windows, Anda memiliki masalah tentang cara menghapus file yang dapat dieksekusi dari hasil
GetModuleFileName()
. Panggilan Windows APIPathRemoveFileSpec()
yang digunakan Nate untuk tujuan itu dalam jawabannya berubah antara Windows 8 dan pendahulunya. Jadi bagaimana agar tetap kompatibel dengan keduanya dan aman? Untungnya, ada C ++ 17 (atau Boost, jika Anda menggunakan kompiler lama). Saya melakukan ini:sumber
Seperti yang disebutkan orang lain,
argv[0]
ini adalah solusi yang cukup bagus, asalkan platform tersebut benar-benar melewati jalur yang dapat dieksekusi, yang tentunya tidak kurang mungkin daripada OS menjadi Windows (di mana WinAPI dapat membantu menemukan jalur yang dapat dieksekusi). Jika Anda ingin menghapus string untuk hanya menyertakan jalur ke direktori tempat eksekutabel berada, maka menggunakan jalur tersebut untuk menemukan file aplikasi lain (seperti aset game jika program Anda adalah game) tidak masalah, karena membuka file relatif terhadap direktori kerja, atau, jika tersedia, root.sumber
Inilah yang akhirnya saya dapatkan
File header terlihat seperti ini:
Penerapan
sumber
Perpustakaan SDL2 ( https://www.libsdl.org/ ) memiliki dua fungsi yang diterapkan di berbagai platform:
Jadi jika Anda tidak ingin menemukan kembali roda ... sayangnya, itu berarti menyertakan seluruh perpustakaan, meskipun memiliki lisensi yang cukup permisif dan seseorang juga dapat menyalin kodenya. Selain itu, ini menyediakan banyak fungsi lintas platform lainnya.
sumber
Ini mungkin cara paling alami untuk melakukannya, sambil mencakup sebagian besar platform desktop utama. Saya tidak yakin, tapi saya yakin ini harus bekerja dengan semua BSD, bukan hanya FreeBSD, jika Anda mengubah pemeriksaan makro platform untuk mencakup semuanya. Jika saya pernah menginstal Solaris, saya pasti akan menambahkan platform itu ke daftar yang didukung.
Menampilkan dukungan penuh UTF-8 di Windows, yang tidak semua orang cukup peduli untuk melangkah sejauh itu.
procinfo / win32 / procinfo.cpp
procinfo / macosx / procinfo.cpp
procinfo / linux / procinfo.cpp
procinfo / freebsd / procinfo.cpp
procinfo / procinfo.cpp
procinfo / procinfo.h
Hal ini memungkinkan mendapatkan path lengkap ke eksekusi dari hampir semua id proses, kecuali pada Windows ada beberapa proses dengan atribut keamanan yang tidak mengizinkannya, jadi wysiwyg, solusi ini tidak sempurna.
Untuk menjawab pertanyaan yang diajukan dengan lebih tepat, Anda dapat melakukan ini:
procinfo.cpp
Bangun struktur file di atas dengan perintah ini:
procinfo.sh
Untuk mengunduh salinan file yang tercantum di atas:
Untuk lebih banyak kebaikan terkait proses lintas platform:
https://github.com/time-killer-games/enigma-dev
Lihat readme untuk daftar sebagian besar fungsi yang disertakan.
sumber
Jika menggunakan C ++ 17 seseorang dapat melakukan hal berikut untuk mendapatkan jalur ke file yang dapat dieksekusi.
Jawaban di atas telah diuji pada Debian 10 menggunakan G ++ 9.3.0
sumber
Mulai C ++ 17:
Pastikan Anda menyertakan filesystem std.
dan sekarang Anda bisa melakukan ini.
boost filesystem menjadi bagian dari lib standar.
jika Anda tidak dapat menemukannya, coba lihat di bawah:
sumber
Ini adalah solusi saya di Windows. Disebut seperti ini:
Di mana 64 adalah ukuran minimum yang menurut Anda akan dilalui. GetPathOfEXE memanggil dirinya sendiri secara rekursif, menggandakan ukuran buffer setiap kali hingga mendapatkan buffer yang cukup besar untuk mendapatkan seluruh jalur tanpa pemotongan.
sumber
new
dan (salah)delete
? Jika Anda menggunakan astd::vector
, kode Anda tidak akan menunjukkan perilaku yang tidak ditentukan.GetModuleFileNameW
tidak mengatur kode kesalahan terakhir jika berhasil. Kode itu rusak dalam banyak hal. Jangan gunakan jika Anda kebetulan menemukan ini.sumber
PathRemoveFileSpec()
dan fungsi terkait sebagai gantinya.di Unix (termasuk Linux) coba 'yang', di Windows coba 'di mana'.
sumber
Metode ini berfungsi untuk Windows dan Linux:
sumber