এক্সিকিউটেবলের পথ পান


114

আমি জানি এই প্রশ্নটি আগে জিজ্ঞাসা করা হয়েছিল তবে আমি এখনও সন্তোষজনক উত্তর, বা একটি নির্দিষ্ট "না, এটি করা যায় না" দেখিনি, তাই আমি আবার জিজ্ঞাসা করব!

আমি এখন যা করতে চাই তা হ'ল বর্তমান চলমান এক্সিকিউটেবলের পথ পেতে হয় নিরঙ্কুশ পথ হিসাবে বা নির্বাহী যেখান থেকে আহবান করা হয়েছে তার সাথে সম্পর্কিত, প্ল্যাটফর্ম-স্বতন্ত্র ফ্যাশনে। যদিও আমি উত্সাহিত :: ফাইল সিস্টেম :: প্রারম্ভিক_পথটি ছিল আমার সমস্যাগুলির জবাব তবে এটি কেবল 'প্ল্যাটফর্ম-স্বতন্ত্র' প্রশ্নের অংশটিকেই পরিচালনা করতে পারে - এটি এখনও সেই পথটি প্রত্যাবর্তন করে যা থেকে অ্যাপ্লিকেশনটি চাওয়া হয়েছিল।

কিছুটা ব্যাকগ্রাউন্ডের জন্য, এটি ওগ্রে ব্যবহার করে একটি গেম, যা আমি খুব স্লিপ ব্যবহার করে প্রোফাইলের চেষ্টা করছি যা লক্ষ্যটি নিজের ডিরেক্টরি থেকে চালানো যায়, সুতরাং অবশ্যই লোডে গেমটির কোনও কনফিগারেশন ফাইল পাওয়া যায় না এবং তত্ক্ষণাত ক্র্যাশ হয় hes । আমি এটি কনফিগারেশন ফাইলগুলির একটি নিখুঁত পথটি পার করতে সক্ষম হতে চাই, যা আমি জানি যে সর্বদা এক্সিকিউটেবলের পাশাপাশি থাকবে। ভিজ্যুয়াল স্টুডিওতে ডিবাগিংয়ের ক্ষেত্রেও এটি একই রকম - আমি ওয়ার্কিং ডিরেক্টরিটি সেট না করেই $ (টার্গেটপথ) চালাতে সক্ষম হতে চাই।



9
মনে রাখবেন যে কোনও উত্তর অনুপস্থিতি প্রমাণ করা অসম্ভব, সুতরাং আপনি একটি নির্দিষ্ট নম্বর পেতে পারেন না । আমি আপনাকে কোনও
অনুমোদনযোগ্য নম্বর


" লোডে গেমটি কোনও কনফিগারেশন ফাইল ইত্যাদি খুঁজে পায় না " তাই গেমটি বর্তমান ডিরেক্টরিতে কনফিগারেশন ফাইলগুলির সন্ধান করে? এটি একটি খারাপ ধারণা এবং সম্ভাব্যরূপে সুরক্ষার দুর্বলতা। কনফিগারেশন ফাইলগুলি একটি আদর্শ স্থানে সংরক্ষণ করা উচিত।
কৌতূহলী

1
আমি এখানে সম্পর্কিত সম্পর্কিত একটি উত্তর পোস্ট করেছিলাম যা আপনার উত্তরও দেয়, বুস্ট ব্যবহার করে প্ল্যাটফর্ম জুড়ে কাজ করে
jtbr

উত্তর:


86

আমি জানি যে কোনও ক্রস প্ল্যাটফর্ম উপায় নেই।

লিনাক্সের জন্য: রিডলিংক / প্রোক / স্ব / এক্সি

উইন্ডোজ: getModuleFileName ame


9
প্ল্যাটফর্মের স্বাধীনতা কেবল প্ল্যাটফর্ম নির্ভরতা আড়াল করার বিষয়। এক্ষেত্রে পদ্ধতিটি নির্বাচন করতে পূর্বনির্ধারিত ওএস ম্যাক্রোগুলি পূর্বনির্ধারিত.সোর্সফোর্জন.টেন / প্রিপোস.চ.টি.এম.এল বিশদে ব্যবহার করা সহজবোধ্য।
ক্লিফোর্ড 15

4
সুতরাং যখনই তারা সি ++ তে এক্সিকিউটেবলের পথ খুঁজে পেতে চান তখনই কি এই কাজটি করে? আমি আশা করছিলাম এমন কিছু সরল-সাউন্ডিংয়ের মতো যা ইতিমধ্যে বুস্টের মতো একটি লাইব্রেরিতে প্রয়োগ করা হবে।
বেন হ্যামার্স

2
আমি আপনাকে নিশ্চিত বুঝতে পারি না যে আমি আপনাকে বুঝতে পেরেছি; আমি নিশ্চিত যে এটি এই প্রশ্নের পুরো পয়েন্ট :)
বেন হাইমার

6
@ কুরিয়াসগুয়ে: আপনি এটি করতে চাইবেন, উদাহরণস্বরূপ, যদি আপনার প্রোগ্রামটি ব্যবহারকারীর চয়ন করার একটি ডিরেক্টরিতে ইনস্টল হয়ে যায়। আপনার এক্সিকিউটেবল এবং এর সমর্থন ফাইলগুলি কোনওভাবে
গ্রেফ্যাড

1
@ হাঁ আপনি কি আমার উত্তরটির লিঙ্ক সহ আপনার উত্তরটি আপডেট করবেন? আমার মন্তব্য তালিকা নিচে সমাহিত করা হয়।
গ্রেগরি পাকোসজ

35

বুস্ট :: Dll :: program_location ফাংশন চলমান এক্সিকিউটেবল যে আমি জানি পথ পাবার সেরা ক্রস প্ল্যাটফর্ম পদ্ধতি এক। ডিএলএল গ্রন্থাগারটি বুস্টে 1.61.0 সংস্করণে যুক্ত করা হয়েছিল।

নিম্নলিখিত আমার সমাধান। আমি এটি উইন্ডোজ, ম্যাক ওএস এক্স, সোলারিস, ফ্রি বিএসডি এবং জিএনইউ / লিনাক্সে পরীক্ষা করেছি।

এটি প্রয়োজন বুস্ট 1.55.0 বা তার অধিক। এটি বুস্ট.ফাইলেস্টেম লাইব্রেরিটি সরাসরি এবং বুস্ট.লোক্যাল লাইব্রেরি এবং বুস্ট.সিস্টেম লাইব্রেরিকে অপ্রত্যক্ষভাবে ব্যবহার করে।

src / executable_path.cpp

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/predef.h>
#include <boost/version.hpp>
#include <boost/tokenizer.hpp>

#if (BOOST_VERSION > BOOST_VERSION_NUMBER(1,64,0))
#  include <boost/process.hpp>
#endif

#if (BOOST_OS_CYGWIN || BOOST_OS_WINDOWS)
#  include <Windows.h>
#endif

#include <boost/executable_path.hpp>
#include <boost/detail/executable_path_internals.hpp>

namespace boost {

#if (BOOST_OS_CYGWIN || BOOST_OS_WINDOWS)

std::string executable_path(const char* argv0)
{
  typedef std::vector<char> char_vector;
  typedef std::vector<char>::size_type size_type;
  char_vector buf(1024, 0);
  size_type size = buf.size();
  bool havePath = false;
  bool shouldContinue = true;
  do
  {
    DWORD result = GetModuleFileNameA(nullptr, &buf[0], size);
    DWORD lastError = GetLastError();
    if (result == 0)
    {
      shouldContinue = false;
    }
    else if (result < size)
    {
      havePath = true;
      shouldContinue = false;
    }
    else if (
      result == size
      && (lastError == ERROR_INSUFFICIENT_BUFFER || lastError == ERROR_SUCCESS)
      )
    {
      size *= 2;
      buf.resize(size);
    }
    else
    {
      shouldContinue = false;
    }
  } while (shouldContinue);
  if (!havePath)
  {
    return detail::executable_path_fallback(argv0);
  }
  // On Microsoft Windows, there is no need to call boost::filesystem::canonical or
  // boost::filesystem::path::make_preferred. The path returned by GetModuleFileNameA
  // is the one we want.
  std::string ret = &buf[0];
  return ret;
}

#elif (BOOST_OS_MACOS)

#  include <mach-o/dyld.h>

std::string executable_path(const char* argv0)
{
  typedef std::vector<char> char_vector;
  char_vector buf(1024, 0);
  uint32_t size = static_cast<uint32_t>(buf.size());
  bool havePath = false;
  bool shouldContinue = true;
  do
  {
    int result = _NSGetExecutablePath(&buf[0], &size);
    if (result == -1)
    {
      buf.resize(size + 1);
      std::fill(std::begin(buf), std::end(buf), 0);
    }
    else
    {
      shouldContinue = false;
      if (buf.at(0) != 0)
      {
        havePath = true;
      }
    }
  } while (shouldContinue);
  if (!havePath)
  {
    return detail::executable_path_fallback(argv0);
  }
  std::string path(&buf[0], size);
  boost::system::error_code ec;
  boost::filesystem::path p(
    boost::filesystem::canonical(path, boost::filesystem::current_path(), ec));
  if (ec.value() == boost::system::errc::success)
  {
    return p.make_preferred().string();
  }
  return detail::executable_path_fallback(argv0);
}

#elif (BOOST_OS_SOLARIS)

#  include <stdlib.h>

std::string executable_path(const char* argv0)
{
  std::string ret = getexecname();
  if (ret.empty())
  {
    return detail::executable_path_fallback(argv0);
  }
  boost::filesystem::path p(ret);
  if (!p.has_root_directory())
  {
    boost::system::error_code ec;
    p = boost::filesystem::canonical(
      p, boost::filesystem::current_path(), ec);
    if (ec.value() != boost::system::errc::success)
    {
      return detail::executable_path_fallback(argv0);
    }
    ret = p.make_preferred().string();
  }
  return ret;
}

#elif (BOOST_OS_BSD)

#  include <sys/sysctl.h>

std::string executable_path(const char* argv0)
{
  typedef std::vector<char> char_vector;
  int mib[4]{0};
  size_t size;
  mib[0] = CTL_KERN;
  mib[1] = KERN_PROC;
  mib[2] = KERN_PROC_PATHNAME;
  mib[3] = -1;
  int result = sysctl(mib, 4, nullptr, &size, nullptr, 0);
  if (-1 == result)
  {
    return detail::executable_path_fallback(argv0);
  }
  char_vector buf(size + 1, 0);
  result = sysctl(mib, 4, &buf[0], &size, nullptr, 0);
  if (-1 == result)
  {
    return detail::executable_path_fallback(argv0);
  }
  std::string path(&buf[0], size);
  boost::system::error_code ec;
  boost::filesystem::path p(
    boost::filesystem::canonical(
      path, boost::filesystem::current_path(), ec));
  if (ec.value() == boost::system::errc::success)
  {
    return p.make_preferred().string();
  }
  return detail::executable_path_fallback(argv0);
}

#elif (BOOST_OS_LINUX)

#  include <unistd.h>

std::string executable_path(const char *argv0)
{
  typedef std::vector<char> char_vector;
  typedef std::vector<char>::size_type size_type;
  char_vector buf(1024, 0);
  size_type size = buf.size();
  bool havePath = false;
  bool shouldContinue = true;
  do
  {
    ssize_t result = readlink("/proc/self/exe", &buf[0], size);
    if (result < 0)
    {
      shouldContinue = false;
    }
    else if (static_cast<size_type>(result) < size)
    {
      havePath = true;
      shouldContinue = false;
      size = result;
    }
    else
    {
      size *= 2;
      buf.resize(size);
      std::fill(std::begin(buf), std::end(buf), 0);
    }
  } while (shouldContinue);
  if (!havePath)
  {
    return detail::executable_path_fallback(argv0);
  }
  std::string path(&buf[0], size);
  boost::system::error_code ec;
  boost::filesystem::path p(
    boost::filesystem::canonical(
      path, boost::filesystem::current_path(), ec));
  if (ec.value() == boost::system::errc::success)
  {
    return p.make_preferred().string();
  }
  return detail::executable_path_fallback(argv0);
}

#else

std::string executable_path(const char *argv0)
{
  return detail::executable_path_fallback(argv0);
}

#endif

}

src / বিস্তারিত / executable_path_internals.cpp

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/predef.h>
#include <boost/version.hpp>
#include <boost/tokenizer.hpp>

#if (BOOST_VERSION > BOOST_VERSION_NUMBER(1,64,0))
#  include <boost/process.hpp>
#endif

#if (BOOST_OS_CYGWIN || BOOST_OS_WINDOWS)
#  include <Windows.h>
#endif

#include <boost/executable_path.hpp>
#include <boost/detail/executable_path_internals.hpp>

namespace boost {
namespace detail {

std::string GetEnv(const std::string& varName)
{
  if (varName.empty()) return "";
#if (BOOST_OS_BSD || BOOST_OS_CYGWIN || BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_SOLARIS)
  char* value = std::getenv(varName.c_str());
  if (!value) return "";
  return value;
#elif (BOOST_OS_WINDOWS)
  typedef std::vector<char> char_vector;
  typedef std::vector<char>::size_type size_type;
  char_vector value(8192, 0);
  size_type size = value.size();
  bool haveValue = false;
  bool shouldContinue = true;
  do
  {
    DWORD result = GetEnvironmentVariableA(varName.c_str(), &value[0], size);
    if (result == 0)
    {
      shouldContinue = false;
    }
    else if (result < size)
    {
      haveValue = true;
      shouldContinue = false;
    }
    else
    {
      size *= 2;
      value.resize(size);
    }
  } while (shouldContinue);
  std::string ret;
  if (haveValue)
  {
    ret = &value[0];
  }
  return ret;
#else
  return "";
#endif
}

bool GetDirectoryListFromDelimitedString(
  const std::string& str,
  std::vector<std::string>& dirs)
{
  typedef boost::char_separator<char> char_separator_type;
  typedef boost::tokenizer<
    boost::char_separator<char>, std::string::const_iterator,
    std::string> tokenizer_type;
  dirs.clear();
  if (str.empty())
  {
    return false;
  }
#if (BOOST_OS_WINDOWS)
  const std::string os_pathsep(";");
#else
  const std::string os_pathsep(":");
#endif
  char_separator_type pathSep(os_pathsep.c_str());
  tokenizer_type strTok(str, pathSep);
  typename tokenizer_type::iterator strIt;
  typename tokenizer_type::iterator strEndIt = strTok.end();
  for (strIt = strTok.begin(); strIt != strEndIt; ++strIt)
  {
    dirs.push_back(*strIt);
  }
  if (dirs.empty())
  {
    return false;
  }
  return true;
}

std::string search_path(const std::string& file)
{
  if (file.empty()) return "";
  std::string ret;
#if (BOOST_VERSION > BOOST_VERSION_NUMBER(1,64,0))
  {
    namespace bp = boost::process;
    boost::filesystem::path p = bp::search_path(file);
    ret = p.make_preferred().string();
  }
#endif
  if (!ret.empty()) return ret;
  // Drat! I have to do it the hard way.
  std::string pathEnvVar = GetEnv("PATH");
  if (pathEnvVar.empty()) return "";
  std::vector<std::string> pathDirs;
  bool getDirList = GetDirectoryListFromDelimitedString(pathEnvVar, pathDirs);
  if (!getDirList) return "";
  std::vector<std::string>::const_iterator it = pathDirs.cbegin();
  std::vector<std::string>::const_iterator itEnd = pathDirs.cend();
  for ( ; it != itEnd; ++it)
  {
    boost::filesystem::path p(*it);
    p /= file;
    if (boost::filesystem::exists(p) && boost::filesystem::is_regular_file(p))
    {
      return p.make_preferred().string();
    }
  }
  return "";
}

std::string executable_path_fallback(const char *argv0)
{
  if (argv0 == nullptr) return "";
  if (argv0[0] == 0) return "";
#if (BOOST_OS_WINDOWS)
  const std::string os_sep("\\");
#else
  const std::string os_sep("/");
#endif
  if (strstr(argv0, os_sep.c_str()) != nullptr)
  {
    boost::system::error_code ec;
    boost::filesystem::path p(
      boost::filesystem::canonical(
        argv0, boost::filesystem::current_path(), ec));
    if (ec.value() == boost::system::errc::success)
    {
      return p.make_preferred().string();
    }
  }
  std::string ret = search_path(argv0);
  if (!ret.empty())
  {
    return ret;
  }
  boost::system::error_code ec;
  boost::filesystem::path p(
    boost::filesystem::canonical(
      argv0, boost::filesystem::current_path(), ec));
  if (ec.value() == boost::system::errc::success)
  {
    ret = p.make_preferred().string();
  }
  return ret;
}

}
}

অন্তর্ভুক্ত / বুস্ট / executable_path.hpp

#ifndef BOOST_EXECUTABLE_PATH_HPP_
#define BOOST_EXECUTABLE_PATH_HPP_

#pragma once

#include <string>

namespace boost {
std::string executable_path(const char * argv0);
}

#endif // BOOST_EXECUTABLE_PATH_HPP_

অন্তর্ভুক্ত / বুস্ট / বিস্তারিত / executable_path_internals.hpp

#ifndef BOOST_DETAIL_EXECUTABLE_PATH_INTERNALS_HPP_
#define BOOST_DETAIL_EXECUTABLE_PATH_INTERNALS_HPP_

#pragma once

#include <string>
#include <vector>

namespace boost {
namespace detail {
std::string GetEnv(const std::string& varName);
bool GetDirectoryListFromDelimitedString(
    const std::string& str,
    std::vector<std::string>& dirs);
std::string search_path(const std::string& file);
std::string executable_path_fallback(const char * argv0);
}
}

#endif // BOOST_DETAIL_EXECUTABLE_PATH_INTERNALS_HPP_

আমার কাছে একটি পরীক্ষা প্রকল্প এবং সিএমকে বিল্ড ফাইলগুলি সহ SnKOpen - / সিপিপি / এক্সিকিউটেবল_প্যাথ / ট্রাঙ্ক সহ একটি সম্পূর্ণ প্রকল্প রয়েছে । আমি এখানে সরবরাহিত সংস্করণটির চেয়ে এই সংস্করণটি আরও সম্পূর্ণ। এটি আরও প্ল্যাটফর্ম সমর্থন করে।

আমি নিম্নলিখিত চারটি পরিস্থিতিতে সমস্ত সমর্থিত অপারেটিং সিস্টেমে অ্যাপ্লিকেশনটি পরীক্ষা করেছি।

  1. আপেক্ষিক পাথ, বর্তমান ডিরেক্টরিতে কার্যকর: যেমন। / এক্সিকিউটেবল_পথ_তম
  2. আপেক্ষিক পাথ, অন্য ডিরেক্টরিতে কার্যকর: যেমন। / বিল্ড / এক্সিকিউটেবল_পথ_স্টেস্ট
  3. সম্পূর্ণ পথ: যেমন / কিছু / দির / এক্সিকিউটেবল_পথ_তম
  4. নির্বাহযোগ্য পথে, কেবল ফাইলের নাম: যেমন: এক্সিকিউটেবল_পথ_তম

চারটি দৃশ্যে, এক্সিকিউটেবল_পথ এবং এক্সিকিউটেবল_পাথ_ফলব্যাক উভয়ই কাজ করে এবং একই ফলাফল দেয়।

মন্তব্য

এটি এই প্রশ্নের একটি আপডেট উত্তর। আমি ব্যবহারকারীদের মন্তব্য এবং পরামর্শ বিবেচনার জন্য উত্তর আপডেট করেছি। আমি আমার এসভিএন সংগ্রহস্থলের একটি প্রকল্পের সাথে একটি লিঙ্কও যুক্ত করেছি।


1
এটি যুক্তিসঙ্গত ফলব্যাকগুলির সাথে একটি সম্পূর্ণ সমাধানের মতো দেখাচ্ছে। +1 টি! যদিও একটি প্রশ্ন: স্থির চর [1024] বাফারগুলিকে কোনও ভেক্টর <চার> এর মতো কিছু দিয়ে প্রতিস্থাপন করা কি বোধগম্য হবে যা পথটি প্রাথমিক আকারের চেয়ে বেশি হলে পুনরায় আকার দেওয়া যেতে পারে?
ড্যানিয়েল ওল্ফ

হ্যাঁ. এটি একটি দুর্দান্ত পরামর্শ। অবশ্যই কিছু অতিরিক্ত পরিবর্তন করা দরকার যেমন ত্রুটিগুলি পরীক্ষা করা, বাফারকে আকার পরিবর্তন করা এবং আবার চেষ্টা করা।
বেন কী

1
আমি মনে করি ফ্যালব্যাক সঠিক নয়। argv[0]কেবল এক্সিকিউটেবল নামও হতে পারে, PATHসেক্ষেত্রে * নিক্স সিস্টেমে এটি অনুসন্ধান করা প্রয়োজন ।
মিশা গার্নি

1
আমি এটি ব্যবহার করার চেষ্টা করেছি। তবে এর দরকার বুস্ট, সঠিক? আমি ভেবেছিলাম এটি একক হয়ে গেছে
ম্যানত্তত্ত

1
আপনি আমাকে "বুস্ট :: ডিএল :: প্রোগ্রাম_লোকেশন"
থমাস

31

এইভাবে বুস্ট + আরগভি ব্যবহার করে। আপনি উল্লেখ করেছেন এটি ক্রস প্ল্যাটফর্ম নাও হতে পারে কারণ এটিতে এক্সিকিউটেবলের নাম অন্তর্ভুক্ত থাকতে পারে বা নাও থাকতে পারে। ভাল নিম্নলিখিত কোডটি প্রায় কাজ করা উচিত।

#include <boost/filesystem/operations.hpp>

#include <boost/filesystem/path.hpp>

#include <iostream>

namespace fs = boost::filesystem;


int main(int argc,char** argv)
{
    fs::path full_path( fs::initial_path<fs::path>() );

    full_path = fs::system_complete( fs::path( argv[0] ) );

    std::cout << full_path << std::endl;

    //Without file name
    std::cout << full_path.stem() << std::endl;
    //std::cout << fs::basename(full_path) << std::endl;

    return 0;
}

নীচের কোডটি বর্তমানের কাজ ডিরেক্টরিটি করে যা আপনার প্রয়োজন অনুযায়ী করতে পারে

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

#include <iostream>

namespace fs = boost::filesystem;


int main(int argc,char** argv)
{
    //current working directory
    fs::path full_path( fs::current_path<fs::path>() );

    std::cout << full_path << std::endl;

    std::cout << full_path.stem() << std::endl;
    //std::cout << fs::basepath(full_path) << std::endl;

    return 0;
}

নোট সবেমাত্র উপলব্ধি হয়ে গেছে যে basename() হ্রাস করা হয়েছে তাই স্যুইচ করতে হয়েছিল.stem()


স্টেমটি আমাকে উইন্ডোজটিতে কেবল এক্সিকিউটেবল বিয়োগের পথ এবং প্রসারণ দেবে বলে মনে হয়, তবে এটি একটি সামান্য বিষয়। আমি যেটি জানতে চাই তা হ'ল এটি কীভাবে আর্গভ [0] এর আশেপাশে কাজ করে যা সম্ভবত ভুল হতে পারে? এটি উইন্ডোতে আমার জন্য পরীক্ষার জন্য কাজ করে, তবে তারপরে আরজিভি [0] আসলে কার্যকর করা যায় নিখুঁত পথ হিসাবে, যা সিস্টেম_পম্পূর্ণ এর কাজকে খুব সহজ করে তোলে :)
বেন

1
না - তার কাজের ডিরেক্টরি দরকার নেই। এবং কোন argv সাহায্য করে না। যখন আরজিভিতে কেবলমাত্র সম্পাদনযোগ্য নাম থাকে আপনি কী করবেন ? কী করবেন, যখন প্রোগ্রামটি একটি সিমলিংকের মাধ্যমে আহ্বান করা হয়েছিল?
ইছথিও

4
"// ফাইলের নাম ছাড়াই" - আপনি চান .parent_path(), না .stem()?
ক্লদিউ

2
এটি আমার প্ল্যাটফর্মে (ম্যাকস এল ক্যাপিটান) কাজ করছে বলে মনে হচ্ছে না। পরিবর্তে আমি বর্তমান ওয়ার্কিং ডিরেক্টরিটি পাই। এছাড়াও, যেমন @Claudiuবলা হয়েছে, আমার মনে হয় এটি হওয়া উচিত .parent_path()
samvv

20

আমি লিনাক্স সম্পর্কে নিশ্চিত নই, তবে উইন্ডোজের জন্য এটি ব্যবহার করে দেখুন:

#include <windows.h>
#include <iostream>

using namespace std ;

int main()
{
     char ownPth[MAX_PATH]; 

     // When NULL is passed to GetModuleHandle, the handle of the exe itself is returned
     HMODULE hModule = GetModuleHandle(NULL);
     if (hModule != NULL)
     {
         // Use GetModuleFileName() with module handle to get the path
         GetModuleFileName(hModule, ownPth, (sizeof(ownPth))); 
         cout << ownPth << endl ;
         system("PAUSE");
         return 0;
     }
     else
     {
         cout << "Module handle is NULL" << endl ;
         system("PAUSE");
         return 0;
     }
}

3
নোট করুন যে কেউ ইউনিকোড সমর্থন সহ সংকলন ইভেন্টে WCHAR ownPth..একটি আবৃত আবশ্যক , অবশ্যই ব্যবহার করা উচিত #ifdef UNICODE। যদি তা না হয় তবে প্রদত্ত কোডটি ব্যবহার করুন।
Dr1Ku

1
কেবলমাত্র রেকর্ডের জন্য আমার একটি মজার ঘটনা ঘটছে যেখানে গেটমোডুলডাইরেক্টরি এর ".." অংশগুলির সাথে একটি পথ ফেরায়, যেমন এটি কমান্ড লাইন থেকে লোলটি স্ট্রিংটি খাঁটি কাটাচ্ছে like আসলে এই ক্ষেত্রে ভিজ্যুয়াল স্টুডিও প্রক্রিয়া আরম্ভ করছে .. এবং ডিবাগিং পথের অংশ part something (প্রজেক্টডির) এর মতো কিছু .. / some.exe আমি শ্লিব থেকে পাথক্যানোনিকালাইজ ব্যবহার করেছি তবে এই লিবার বিরুদ্ধে লিঙ্ক করা দরকার। এটি পছন্দসই নাও হতে পারে।
v.oddou

1
আমি চরের পরিবর্তে নিজের প্যাথের জন্য টিসিএইচআর ব্যবহার করার ক্ষতিপূরণও চাই। তবে যাইহোক সুন্দর উত্তর।
শে

এটির পক্ষে কি ব্যর্থ হওয়া সম্ভব? এক নজরে এটি অসম্ভব বলে মনে হচ্ছে ...HMODULE hModule = GetModuleHandle(NULL);
কায়লিফ্রয়_নডেক

1
যদি getModuleFileName এর জন্য প্রথম প্যারামিটারটি NULL হয়, তবে এটি বর্তমান প্রক্রিয়ার এক্সিকিউটেবল ফাইলের পথটি পুনরুদ্ধার করে।
lsalamon

12

উইন্ডোজ জন্য:

GetModuleFileName - উদাহরণ পথ + এক্সাইল ফাইলের নাম দেয়

ফাইলের নাম সরাতে
PathRemoveFileSpec


1
ডক্স PathRemoveFileSpec জন্য নোট: This function is deprecated. We recommend the use of the PathCchRemoveFileSpec function in its place
javs

12

সি ++ 17, উইন্ডোজ, ইউনিকোড, ফাইল সিস্টেম নতুন এপিআই ব্যবহার করে:

#include "..\Project.h"
#include <filesystem>
using namespace std;
using namespace filesystem;

int wmain(int argc, wchar_t** argv)
{
    auto dir = weakly_canonical(path(argv[0])).parent_path();
    printf("%S", dir.c_str());
    return 0;
}

এই সমাধানটি বহনযোগ্য হওয়া উচিত সন্দেহ করুন তবে কীভাবে ইউনিকোড অন্যান্য ওএসে প্রয়োগ করা হয় তা জানেন না।

আপনি আউটপুট ডিরেক্টরি উপরের ফোল্ডার হিসাবে ('..') সরল করার জন্য কেবলমাত্র আউটপুট ডিরেক্টরি হিসাবে ব্যবহার করলেই দুর্বল_কেনোনিকাল প্রয়োজন। যদি আপনি এটি ব্যবহার না করেন - এটি সরান।

আপনি যদি ডায়নামিক লিঙ্ক লাইব্রেরি (.dll /.so) থেকে অপারেটিং করে থাকেন তবে আপনার আরগভি নাও থাকতে পারে, তবে নিম্নলিখিত সমাধানগুলি বিবেচনা করতে পারেন:

application.h:

#pragma once

//
// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
//
#ifdef __cpp_lib_filesystem
#include <filesystem>
#else
#include <experimental/filesystem>

namespace std {
    namespace filesystem = experimental::filesystem;
}
#endif

std::filesystem::path getexepath();

application.cpp:

#include "application.h"
#ifdef _WIN32
#include <windows.h>    //GetModuleFileNameW
#else
#include <limits.h>
#include <unistd.h>     //readlink
#endif

std::filesystem::path getexepath()
{
#ifdef _WIN32
    wchar_t path[MAX_PATH] = { 0 };
    GetModuleFileNameW(NULL, path, MAX_PATH);
    return path;
#else
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
#endif
}

শিরোলেখের অভ্যন্তরে প্রহরীরা ফাইল সিস্টেমের উপস্থিতির জন্য যথাযথ পরীক্ষা করে না। cppreferences দেখায় যে বৈশিষ্ট্য পরীক্ষার ম্যাক্রোর মানটি ফাইল সিস্টেমের শিরোনামেই সংজ্ঞায়িত করা হয়, সুতরাং এটি অন্তর্ভুক্ত করার আগে পরীক্ষা করতে কাজ করে না। __হাস_মিনে অন্তর্ভুক্ত () এখানে একটি আরও ভাল স্ট্যান্ডার্ড পরীক্ষা।
মেটিওরহেড

8

কিউটি কিউরে অ্যাপ্লিকেশন :: অ্যাপ্লিকেশনডিরপথ () হিসাবে ওএস বিমূর্তি সরবরাহ করে


এই সঙ্গে পথ: QCoreApplication::applicationDirPath: Please instantiate the QApplication object first। কীভাবে সমাধান করা যায় কোন ধারণা?
গাইসফট

@ গুয়াসফট: সহজভাবে এর QCoreApplicationমতো একটি উদাহরণ তৈরি করুন QApplication application(argc, argv);(এটি আপনার করুন main(argc, argv)এবং এটি নিশ্চিত করুন যে আপনি argc/argvকিউকোর অ্যাপ্লিকেশন ( ডকুমেন্টেশন চেক করুন ) এর আজীবন ধরে বৈধ থাকতে হবে
টেড করুন

5

এটি একটি উইন্ডোজ নির্দিষ্ট উপায়, তবে এটি আপনার উত্তরের কমপক্ষে অর্ধেক।

GetThisPath.h

/// dest is expected to be MAX_PATH in length.
/// returns dest
///     TCHAR dest[MAX_PATH];
///     GetThisPath(dest, MAX_PATH);
TCHAR* GetThisPath(TCHAR* dest, size_t destSize);

GetThisPath.cpp

#include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

TCHAR* GetThisPath(TCHAR* dest, size_t destSize)
{
    if (!dest) return NULL;
    if (MAX_PATH > destSize) return NULL;

    DWORD length = GetModuleFileName( NULL, dest, destSize );
    PathRemoveFileSpec(dest);
    return dest;
}

mainProgram.cpp

TCHAR dest[MAX_PATH];
GetThisPath(dest, MAX_PATH);

আমি প্ল্যাটফর্ম সনাক্তকরণকে GetThisPathপ্রতিটি প্ল্যাটফর্মের জন্য কল করে এমন একটি মোড়ক ফাংশন বাস্তবায়নের পরিবর্তনের জন্য প্রিপ্রোসেসর নির্দেশিকা হিসাবে ব্যবহার করার পরামর্শ দেব ।


3

আরগস ব্যবহার করে [0] এবং '/' (বা '\\') খুঁজছেন:

#include <string>
#include <iostream> // to show the result

int main( int numArgs, char *args[])
{
    // Get the last position of '/'
    std::string aux(args[0]);

    // get '/' or '\\' depending on unix/mac or windows.
#if defined(_WIN32) || defined(WIN32)
    int pos = aux.rfind('\\');
#else
    int pos = aux.rfind('/');
#endif

    // Get the path and the name
    std::string path = aux.substr(0,pos+1);
    std::string name = aux.substr(pos+1);
    // show results
    std::cout << "Path: " << path << std::endl;
    std::cout << "Name: " << name << std::endl;
}

সম্পাদিত: যদি '/' উপস্থিত না থাকে, পোস্ট == - 1 সুতরাং ফলাফলটি সঠিক।


'/' পথে উপস্থিত না থাকলে কী হবে? এই মামলার কোনও তদন্ত নেই এবং আমি বিশ্বাস করি এটি বেশ সম্ভবত - উইন্ডোজ ব্যাকস্ল্যাশ ব্যবহার করবে, এবং args[0]বাস্তবে এটি কোনও পথই নাও হতে পারে।
বেন হাইমার 13

যদি '/' উপস্থিত না থাকে, rfind ফিরে -1, সুতরাং "পথ" = aux.substr (0,0) এবং "নাম" = aux.substr (0): ফলাফলটি সঠিক। উইন্ডোজের সাথে সম্পর্কিত, আপনি ঠিক বলেছেন, '/' অবশ্যই '\\' এ পরিবর্তন করতে হবে, আমি উইন্ডোগুলিকেও অনুমতি দেওয়ার জন্য পরিবর্তন করব। আমি '/' দিয়ে ফাইলের নামের জন্যও পরীক্ষা করেছি, তবে এটি সর্বশেষে কোডেড এবং সমস্যা তৈরি করে না।
অ্যাড্রিয়ান মাইর

1
args[0]অগত্যা নির্বাহযোগ্য পথ যা আমাকে বিরক্ত করে তা না হওয়ার বিষয়ে এটি আরও বেশি অংশ । যদিও উইন্ডোজের জন্য আপনার উত্তর ঠিক করার জন্য ধন্যবাদ :)
বেন হাইমার

1
যদি কমান্ডটি পথ না দিয়ে চালানো হয় (অর্থাত্ এটি PATH এনভিরভ ডিরেক্টরিতে দেওয়া ডিরেক্টরিতে পাওয়া যায়), আরগস [0] কেবলমাত্র নির্বাহের নাম, পথ ছাড়াই হবে।
কেভিন

@ কেভিন: আপনি (এবং অন্যরা) ঠিক বলেছেন, ছোট সরঞ্জামগুলির জন্য এটি একটি সহজ সমাধান that 95% ক্ষেত্রে কাজ করে। গুরুতর সফ্টওয়্যার জন্য, একটি কনফিগারেশন ফাইল এবং / অথবা পরিবেশের পরিবর্তনশীল সম্ভবত আরও ভাল। এছাড়াও, এটি সাধারণত খুব ভাল (বা এমনকি ভুল) ডিজাইন বোঝায় না।
অ্যাড্রিয়ান মাইয়ার


1

নিম্নলিখিতটি দ্রুত এবং নোংরা সমাধান হিসাবে কাজ করে তবে মনে রাখবেন যে এটি নির্বোধ থেকে দূরে:

#include <iostream>

using namespace std ;

int main( int argc, char** argv)
{
    cout << argv[0] << endl ;
    return 0;
}

17
আমি অন্যান্য এসও প্রশ্নগুলিতে দেখেছি যে এটি সর্বদা কার্যকর হয় না, এবং এই আরজিভি [0] এ মৃত্যুদন্ড কার্যকর করতে পারে, কেবল মৃত্যুদন্ড কার্যকর করার ফাইলের নাম, বা অন্য কোনও আবর্জনার জন্য নিখুঁত পথ থাকতে পারে।
বেন হ্যামার্স

7
যদি তারা 'সাপোর্ট ফাইল' বা এ জাতীয় পছন্দগুলি খোলার চেষ্টা করে তবে আরগভি [0] কে কখনই বিশ্বাস করা উচিত নয়। আরজিভি পরিবর্তন সাপেক্ষে, এবং যে কোনও কলকারী মন্দ এটি এর মান পরিবর্তন করতে পারে। আপনি এটি লগিং ইত্যাদির জন্য ব্যবহার না করা অবধি এড়িয়ে চলুন, ফাইল খোলার জন্য ব্যবহৃত পাথ তৈরির জন্য নয়।
কিউস - মনিকা 24

এটি উইন্ডোজে কাজ করে না। argv [0] এর পুরো পথ থাকবে না। কেবলমাত্র .exe ফাইল। দয়া করে, কোনও ব্যাশ শেল ব্যবহার করে চেষ্টা করবেন না, এটি প্রমিত উত্পাদনের জন্য স্ট্যান্ডার্ড কনসোল এবং cout << আরগভি [0] এ চেষ্টা করুন।
ফ্রেডি মার্টিনেজ গার্সিয়া

@ ফ্রেডিমার্টিনিজগার্সিয়া ওয়েল আমি এটি উইন্ডোতে পরীক্ষা করতাম, তাই ওয়াইএমএমভি। কোডটি চালু করতে যা কিছু ব্যবহৃত হয়েছিল তা এটি। আপনি যদি সিডাব্লুডিতে নির্বাহযোগ্য হন তবে নিশ্চিত হন যে আপনি কেবল ফাইলের নাম পাবেন get
ক্লিফোর্ড

0

উইন্ডোজের জন্য আপনাকে ইউনিকোড পাথগুলি পরিচালনা করতে হবে:

#include <Windows.h>
#include <iostream>

int wmain(int argc, wchar_t * argv[])
{
    HMODULE this_process_handle = GetModuleHandle(NULL);
    wchar_t this_process_path[MAX_PATH];

    GetModuleFileNameW(NULL, this_process_path, sizeof(this_process_path));

    std::wcout << "Unicode path of this app: " << this_process_path << std::endl;

    return 0;
}

0

উইন্ডোজের জন্য, আপনার ফলাফলটি থেকে এক্সিকিউটিভকে কীভাবে ফেলা যায় তা নিয়ে সমস্যা রয়েছে GetModuleFileName()PathRemoveFileSpec()তার উত্তরে সেই উদ্দেশ্যে উইন্ডোজ এপিআই কলটি উইন্ডোজ 8 এবং এর পূর্বসূরীদের মধ্যে পরিবর্তিত হয়েছিল। তাহলে কীভাবে সুরক্ষিত এবং সুরক্ষিত উভয়ের সাথে সামঞ্জস্য থাকতে পারি? ভাগ্যক্রমে, সি ++ 17 রয়েছে (বা বুস্ট, যদি আপনি কোনও পুরানো সংকলক ব্যবহার করছেন)। আমি এই কাজ:

#include <windows.h>
#include <string>
#include <filesystem>
namespace fs = std::experimental::filesystem;

// We could use fs::path as return type, but if you're not aware of
// std::experimental::filesystem, you probably handle filenames
// as strings anyway in the remainder of your code.  I'm on Japanese
// Windows, so wide chars are a must.
std::wstring getDirectoryWithCurrentExecutable()
{
    int size = 256;
    std::vector<wchar_t> charBuffer;
    // Let's be safe, and find the right buffer size programmatically.
    do {
        size *= 2;
        charBuffer.resize(size);
        // Resize until filename fits.  GetModuleFileNameW returns the
        // number of characters written to the buffer, so if the
        // return value is smaller than the size of the buffer, it was
        // large enough.
    } while (GetModuleFileNameW(NULL, charBuffer.data(), size) == size);
    // Typically: c:/program files (x86)/something/foo/bar/exe/files/win64/baz.exe
    // (Note that windows supports forward and backward slashes as path
    // separators, so you have to be careful when searching through a path
    // manually.)

    // Let's extract the interesting part:
    fs::path path(charBuffer.data());  // Contains the full path including .exe
    return path.remove_filename()  // Extract the directory ...
               .w_str();           // ... and convert to a string.
}

0

অন্যরা যেমন উল্লেখ করেছেন, argv[0]এটি একটি দুর্দান্ত সমাধান, তবে শর্ত থাকে যে প্ল্যাটফর্মটি বাস্তবায়িত পথটি পাস করে, যা ওএস উইন্ডোজ হওয়ার চেয়ে অবশ্যই কম সম্ভাবনা নয় (যেখানে উইনাপি এক্সিকিউটেবল পাথ খুঁজতে সহায়তা করতে পারে)। যদি আপনি কেবল নির্বাহী স্থানে থাকে এমন ডিরেক্টরিতে যাওয়ার পথটি অন্তর্ভুক্ত করতে স্ট্রিংটি স্ট্র্যাপ করতে চান তবে অন্যান্য অ্যাপ্লিকেশন ফাইলগুলি খুঁজে পাওয়ার জন্য সেই পাথটি ব্যবহার করে (যেমন আপনার প্রোগ্রামটি যদি গেম হিসাবে থাকে তবে গেমের সম্পদগুলি) পুরোপুরি ঠিক আছে, কারণ ফাইলগুলি খোলার সাথে সম্পর্কিত ওয়ার্কিং ডিরেক্টরি, বা, সরবরাহ করা হলে, মূল।


0

এটিই আমি শেষ করেছি

শিরোনাম ফাইলটি দেখতে এমন দেখাচ্ছে:

#pragma once

#include <string>
namespace MyPaths {

  std::string getExecutablePath();
  std::string getExecutableDir();
  std::string mergePaths(std::string pathA, std::string pathB);
  bool checkIfFileExists (const std::string& filePath);

}

বাস্তবায়ন


#if defined(_WIN32)
    #include <windows.h>
    #include <Shlwapi.h>
    #include <io.h> 

    #define access _access_s
#endif

#ifdef __APPLE__
    #include <libgen.h>
    #include <limits.h>
    #include <mach-o/dyld.h>
    #include <unistd.h>
#endif

#ifdef __linux__
    #include <limits.h>
    #include <libgen.h>
    #include <unistd.h>

    #if defined(__sun)
        #define PROC_SELF_EXE "/proc/self/path/a.out"
    #else
        #define PROC_SELF_EXE "/proc/self/exe"
    #endif

#endif

namespace MyPaths {

#if defined(_WIN32)

std::string getExecutablePath() {
   char rawPathName[MAX_PATH];
   GetModuleFileNameA(NULL, rawPathName, MAX_PATH);
   return std::string(rawPathName);
}

std::string getExecutableDir() {
    std::string executablePath = getExecutablePath();
    char* exePath = new char[executablePath.length()];
    strcpy(exePath, executablePath.c_str());
    PathRemoveFileSpecA(exePath);
    std::string directory = std::string(exePath);
    delete[] exePath;
    return directory;
}

std::string mergePaths(std::string pathA, std::string pathB) {
  char combined[MAX_PATH];
  PathCombineA(combined, pathA.c_str(), pathB.c_str());
  std::string mergedPath(combined);
  return mergedPath;
}

#endif

#ifdef __linux__

std::string getExecutablePath() {
   char rawPathName[PATH_MAX];
   realpath(PROC_SELF_EXE, rawPathName);
   return  std::string(rawPathName);
}

std::string getExecutableDir() {
    std::string executablePath = getExecutablePath();
    char *executablePathStr = new char[executablePath.length() + 1];
    strcpy(executablePathStr, executablePath.c_str());
    char* executableDir = dirname(executablePathStr);
    delete [] executablePathStr;
    return std::string(executableDir);
}

std::string mergePaths(std::string pathA, std::string pathB) {
  return pathA+"/"+pathB;
}

#endif

#ifdef __APPLE__
    std::string getExecutablePath() {
        char rawPathName[PATH_MAX];
        char realPathName[PATH_MAX];
        uint32_t rawPathSize = (uint32_t)sizeof(rawPathName);

        if(!_NSGetExecutablePath(rawPathName, &rawPathSize)) {
            realpath(rawPathName, realPathName);
        }
        return  std::string(realPathName);
    }

    std::string getExecutableDir() {
        std::string executablePath = getExecutablePath();
        char *executablePathStr = new char[executablePath.length() + 1];
        strcpy(executablePathStr, executablePath.c_str());
        char* executableDir = dirname(executablePathStr);
        delete [] executablePathStr;
        return std::string(executableDir);
    }

    std::string mergePaths(std::string pathA, std::string pathB) {
        return pathA+"/"+pathB;
    }
#endif


bool checkIfFileExists (const std::string& filePath) {
   return access( filePath.c_str(), 0 ) == 0;
}

}

0

এসডিএল 2 ( https://www.libsdl.org/ ) গ্রন্থাগারের প্ল্যাটফর্মের বিস্তৃত বর্ণালী জুড়ে দুটি ফাংশন প্রয়োগ করা হয়েছে:

  • SDL_GetBasePath
  • SDL_GetPrefPath

সুতরাং আপনি যদি চক্রটি পুনরায় উদ্ভাবন করতে না চান ... তবে দুঃখের বিষয়, এর অর্থ পুরো লাইব্রেরিটি সহ, যদিও এটি একটি বেশিরভাগ অনুমতিপ্রাপ্ত লাইসেন্স পেয়েছে এবং একটিতে কেবল কোডটি অনুলিপি করা যেতে পারে। এছাড়াও এটি ক্রস প্ল্যাটফর্মের অনেকগুলি কার্যকারিতা সরবরাহ করে।


0

বেশিরভাগ প্রধান ডেস্কটপ প্ল্যাটফর্মগুলিকে coveringেকে রাখার সময় এটি সম্ভবত সবচেয়ে প্রাকৃতিক উপায়। আমি নিশ্চিত নই, তবে আমি বিশ্বাস করি যে এই সমস্তটি কভার করার জন্য প্ল্যাটফর্মের ম্যাক্রো চেকটি পরিবর্তন করা হলে কেবল ফ্রিবিএসডি নয়, সমস্ত বিএসডি'র সাথে কাজ করা উচিত। আমি যদি কখনও সোলারিস ইনস্টল করার আশেপাশে যাই তবে আমি অবশ্যই প্ল্যাটফর্মটিকে সমর্থিত তালিকায় যুক্ত করব।

উইন্ডোজে সম্পূর্ণ ইউটিএফ -8 সমর্থন বৈশিষ্ট্যযুক্ত, যা প্রত্যেকে এতদূর যাওয়ার জন্য যথেষ্ট যত্ন করে না।

procinfo / Win32 / procinfo.cpp

#ifdef _WIN32
#include "../procinfo.h"
#include <windows.h>
#include <tlhelp32.h>
#include <cstddef>
#include <vector>
#include <cwchar>

using std::string;
using std::wstring;
using std::vector;
using std::size_t;

static inline string narrow(wstring wstr) {
  int nbytes = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.length(), NULL, 0, NULL, NULL);
  vector<char> buf(nbytes);
  return string{ buf.data(), (size_t)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.length(), buf.data(), nbytes, NULL, NULL) };
}

process_t ppid_from_pid(process_t pid) {        
  process_t ppid;       
  HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);      
  PROCESSENTRY32 pe = { 0 };        
  pe.dwSize = sizeof(PROCESSENTRY32);       
  if (Process32First(hp, &pe)) {        
    do {        
      if (pe.th32ProcessID == pid) {        
        ppid = pe.th32ParentProcessID;      
        break;      
      }     
    } while (Process32Next(hp, &pe));       
  }     
  CloseHandle(hp);      
  return ppid;      
}

string path_from_pid(process_t pid) {
  string path;
  HANDLE hm = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
  MODULEENTRY32W me = { 0 };
  me.dwSize = sizeof(MODULEENTRY32W);
  if (Module32FirstW(hm, &me)) {
    do {
      if (me.th32ProcessID == pid) {
        path = narrow(me.szExePath);
        break;
      }
    } while (Module32NextW(hm, &me));
  }
  CloseHandle(hm);
  return path;
}
#endif

procinfo / macosx / procinfo.cpp

#if defined(__APPLE__) && defined(__MACH__)
#include "../procinfo.h"
#include <libproc.h>

using std::string;

string path_from_pid(process_t pid) {
  string path;
  char buffer[PROC_PIDPATHINFO_MAXSIZE];
  if (proc_pidpath(pid, buffer, sizeof(buffer)) > 0) {
    path = string(buffer) + "\0";
  }
  return path;
}
#endif

procinfo / লিনাক্স / procinfo.cpp

#ifdef __linux__
#include "../procinfo.h"
#include <cstdlib>

using std::string;
using std::to_string;

string path_from_pid(process_t pid) {
  string path;
  string link = string("/proc/") + to_string(pid) + string("/exe");
  char *buffer = realpath(link.c_str(), NULL);
  path = buffer ? : "";
  free(buffer);
  return path;
}
#endif

procinfo / FreeBSD / procinfo.cpp

#ifdef __FreeBSD__
#include "../procinfo.h"
#include <sys/sysctl.h>
#include <cstddef>

using std::string;
using std::size_t;

string path_from_pid(process_t pid) {
  string path;
  size_t length;
  // CTL_KERN::KERN_PROC::KERN_PROC_PATHNAME(pid)
  int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid };
  if (sysctl(mib, 4, NULL, &length, NULL, 0) == 0) {
    path.resize(length, '\0');
    char *buffer = path.data();
    if (sysctl(mib, 4, buffer, &length, NULL, 0) == 0) {
      path = string(buffer) + "\0";
    }
  }
  return path;
}
#endif

procinfo / procinfo.cpp

#include "procinfo.h"
#ifdef _WiN32
#include <process.h>
#endif
#include <unistd.h>
#include <cstddef>

using std::string;
using std::size_t;

process_t pid_from_self() {
  #ifdef _WIN32
  return _getpid();
  #else
  return getpid();
  #endif
}

process_t ppid_from_self() {
  #ifdef _WIN32
  return ppid_from_pid(pid_from_self());
  #else
  return getppid();
  #endif
}

string dir_from_pid(process_t pid) {
  string fname = path_from_pid(pid);
  size_t fp = fname.find_last_of("/\\");
  return fname.substr(0, fp + 1);
}

string name_from_pid(process_t pid) {
  string fname = path_from_pid(pid);
  size_t fp = fname.find_last_of("/\\");
  return fname.substr(fp + 1);
}

procinfo / procinfo.h

#ifdef _WiN32
#include <windows.h>
typedef DWORD process_t;
#else
#include <sys/types.h>
typedef pid_t process_t;
#endif
#include <string>

/* windows-only helper function */
process_t ppid_from_pid(process_t pid);

/* get current process process id */
process_t pid_from_self();

/* get parent process process id */
process_t ppid_from_self();

/* std::string possible_result = "C:\\path\\to\\file.exe"; */
std::string path_from_pid(process_t pid);

/* std::string possible_result = "C:\\path\\to\\"; */
std::string dir_from_pid(process_t pid);

/* std::string possible_result = "file.exe"; */
std::string name_from_pid(process_t pid);

এটি কোনও প্রসেস আইডি কার্যকর করার পুরো পথ পাবে, উইন্ডোজ ব্যতীত এমন কিছু প্রক্রিয়া রয়েছে যা সুরক্ষা বৈশিষ্ট্যগুলি কেবল এটির অনুমতি দেয় না, সুতরাং উইসুইগ, এই সমাধানটি নিখুঁত নয়।

প্রশ্নটি আরও নির্ভুলভাবে কী জিজ্ঞাসা করছিল তা সম্বোধনের জন্য, আপনি এটি করতে পারেন:

procinfo.cpp

#include "procinfo/procinfo.h"
#include <iostream>

using std::string;
using std::cout;
using std::endl;

int main() {
  cout << dir_from_pid(pid_from_self()) << endl;
  return 0;
}

এই কমান্ডের সাহায্যে উপরের ফাইল কাঠামোটি তৈরি করুন:

procinfo.sh

cd "${0%/*}"
g++ procinfo.cpp procinfo/procinfo.cpp procinfo/win32/procinfo.cpp procinfo/macosx/procinfo.cpp procinfo/linux/procinfo.cpp procinfo/freebsd/procinfo.cpp -o procinfo.exe

উপরে তালিকাভুক্ত ফাইলগুলির একটি অনুলিপি ডাউনলোড করার জন্য:

git clone git://github.com/time-killer-games/procinfo.git

আরও ক্রস-প্ল্যাটফর্ম প্রক্রিয়া-সম্পর্কিত ভালতার জন্য:

https://github.com/time-killer-games/enigma-dev

অন্তর্ভুক্ত বেশিরভাগ কার্যকারিতার তালিকার জন্য রিডমি দেখুন।


0

সি ++ 17 ব্যবহার করা হলে এক্সিকিউটেবলের পথে যাওয়ার জন্য কেউ নিম্নলিখিতটি করতে পারে।

#include <filesystem>

std::filesystem::path getExecutablePath()
{
    return std::filesystem::canonical("/proc/self/exe");
}

উপরের উত্তরটি ডি + 10 তে জি ++ 9.3.0 ব্যবহার করে পরীক্ষা করা হয়েছে


মনে রাখবেন যে এটি কেবল তখনই কাজ করবে যখন / proc / self / exe বিদ্যমান এবং অ্যাক্সেসযোগ্য। আপনার সম্ভবত এটি পরীক্ষা করা উচিত।
জ্রিন

-1

সি ++ 17 অনুসারে:

আপনি std ফাইল সিস্টেম অন্তর্ভুক্ত নিশ্চিত করুন।

#include <filesystem>

এবং এখন আপনি এটি করতে পারেন।

std::filesystem::current_path().string()

বুস্ট ফাইল সিস্টেমটি স্ট্যান্ডার্ড লাইবের একটি অংশে পরিণত হয়েছিল।

যদি আপনি এটির অধীনে দেখার চেষ্টা না করে থাকেন:

std::experimental::filesystem

10
এটি বাইনারিটির পথ নয়, এটি বর্তমান ওয়ার্কিং ডিরেক্টরি।
জিত্রাটেক্স

-2

উইন্ডোজে এটিই আমার সমাধান ছিল। এটিকে এভাবে বলা হয়:

std::wstring sResult = GetPathOfEXE(64);

যেখানে 64 ন্যূনতম আকার হ'ল আপনার মনে হয় পথটি হবে। গেটপ্যাথএফএক্সইএক্স নিজেকে পুনরাবৃত্তভাবে কল করে, প্রতিটি বার বাফারের আকার দ্বিগুণ করে যতক্ষণ না এটি কাটা ছাড়াই পুরো পথটি পাওয়ার জন্য যথেষ্ট পরিমাণে বাফার না পায়।

std::wstring GetPathOfEXE(DWORD dwSize)
{
    WCHAR* pwcharFileNamePath;
    DWORD dwLastError;
    HRESULT hrError;
    std::wstring wsResult;
    DWORD dwCount;

    pwcharFileNamePath = new WCHAR[dwSize];

    dwCount = GetModuleFileNameW(
        NULL,
        pwcharFileNamePath,
        dwSize
    );

    dwLastError = GetLastError();

    if (ERROR_SUCCESS == dwLastError)
    {
        hrError = PathCchRemoveFileSpec(
            pwcharFileNamePath,
            dwCount
        );

        if (S_OK == hrError)
        {
            wsResult = pwcharFileNamePath;

            if (pwcharFileNamePath)
            {
                delete pwcharFileNamePath;
            }

            return wsResult;
        }
        else if(S_FALSE == hrError)
        {
            wsResult = pwcharFileNamePath;

            if (pwcharFileNamePath)
            {
                delete pwcharFileNamePath;
            }

            //there was nothing to truncate off the end of the path
            //returning something better than nothing in this case for the user
            return wsResult;
        }
        else
        {
            if (pwcharFileNamePath)
            {
                delete pwcharFileNamePath;
            }

            std::ostringstream oss;
            oss << "could not get file name and path of executing process. error truncating file name off path. last error : " << hrError;
            throw std::runtime_error(oss.str().c_str());
        }
    }
    else if (ERROR_INSUFFICIENT_BUFFER == dwLastError)
    {
        if (pwcharFileNamePath)
        {
            delete pwcharFileNamePath;
        }

        return GetPathOfEXE(
            dwSize * 2
        );
    }
    else
    {
        if (pwcharFileNamePath)
        {
            delete pwcharFileNamePath;
        }

        std::ostringstream oss;
        oss << "could not get file name and path of executing process. last error : " << dwLastError;
        throw std::runtime_error(oss.str().c_str());
    }
}

ব্যবহারের কারণ newএবং (ভুল) deleteকী? আপনি যদি একটি ব্যবহার করেন তবে std::vectorআপনার কোডটি অপরিজ্ঞাত আচরণ প্রদর্শন করবে না।
IInspectable

তদ্ব্যতীত, GetModuleFileNameWসাফল্যের ক্ষেত্রে সর্বশেষ ত্রুটি কোড সেট করে না। সেই কোডটি অনেক উপায়ে ভাঙা। আপনি যদি এইজন্য হোঁচট খেয়ে পড়েন তবে ব্যবহার করবেন না।
IInspectable

-3
char exePath[512];
CString strexePath;
GetModuleFileName(NULL,exePath,512);
strexePath.Format("%s",exePath);
strexePath = strexePath.Mid(0,strexePath.ReverseFind('\\'));

2
এটি উইন্ডো-কেবল এবং এমএফসি ব্যবহার করে, ক্রস-প্ল্যাটফর্ম হওয়া থেকে অনেক দূরে, দুঃখিত!
বেন হ্যামার্স 20'14

1
এটি এমনকি এটি করার মতো উইন্ডোজ পদ্ধতিও নয়। PathRemoveFileSpec()পরিবর্তে দেখুন এবং সম্পর্কিত ফাংশন।
রেমি Lebeau

-4

ইউনিক্সে (লিনাক্স সহ) চেষ্টা করুন 'যা', উইন্ডোজটিতে 'কোথায়' চেষ্টা করুন।

#include <stdio.h>

#define _UNIX

int main(int argc, char** argv)
{
        char cmd[128];
        char buf[128];
        FILE* fp = NULL;
#if defined(_UNIX)
        sprintf(cmd, "which %s > my.path", argv[0]);
#else
        sprintf(cmd, "where %s > my.path", argv[0]);
#endif
        system(cmd);
        fp = fopen("my.path", "r");
        fgets(buf, sizeof(buf), fp);
        fclose(fp);

        printf("full path: %s\n", buf);
        unlink("my.path");

        return 0;
}

-4

এই পদ্ধতিটি উইন্ডোজ এবং লিনাক্স উভয়ের জন্যই কাজ করে:

#include <stdio.h>
#include <string>
#ifdef _WIN32
#include <direct.h>
#define GetCurrentDir _getcwd
#elif __linux__
#include <unistd.h>
#define GetCurrentDir getcwd
#endif

std::string GetCurrentWorkingDir() 
{
    char buff[FILENAME_MAX];
    GetCurrentDir(buff, FILENAME_MAX);
    std::string current_working_dir(buff);
    return current_working_dir;
}

2
এটি বর্তমান ওয়ার্কিং ডিরেক্টরিটি ফিরিয়ে দেয়, এক্সিকিউটেবলের পথ নয় যা একই জিনিস নাও হতে পারে।
ডেভ ডুর্বিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.