PDA

View Full Version : سوال: روش کپی کردن چند فایل dll در درایو C با زدن یک دکمه



autosystem
شنبه 23 آذر 1398, 12:33 عصر
دوستان درود بر شما، من برنامه ای با VB.NET نوشتم که بعد از شناسایی یه قفل سخت افزاری باید دکمه ای فعال شود و با کلیک کاربر بر روی آن، یک سری فایل DLL (که جزء ریسورس های برنامه هست و باید در دل فایل exe نهایی قرار بگیره و کاربر به آنها دسترسی نداشته باشد)را در پوشه ای در Program file کپی کنه و حتی اگر موجود بودند بر روی آنها overwrite کنه، در واقع انگار که یک برنامه Setup هست. روش های مختلفی را تست کردم که برخی جواب داد اما مشکل این بود که با کپی بر روی درایو C مشکل داشتند و خطای Access denide می دادند.
اساتید محترم لطفا راهنمایی فرمایید

ASHKANLAEI
شنبه 23 آذر 1398, 15:04 عصر
فکر میکنم باید برنامۀ نهایی run as admin باشه که مشکلی ایجاد نشود.

autosystem
شنبه 23 آذر 1398, 15:13 عصر
فکر میکنم باید برنامۀ نهایی run as admin باشه که مشکلی ایجاد نشود.
با سپاس از شما،
بله با Run as admin مشکل حل میشه ولی من نمی خوام به کاربرم بگم که Run as admin بکنه! و مشکل دیگه اینکه اگر کاربر این کار را انجام نده، دات نت ارور میده و داخل ارور هم اسم فایل ها را مینویسه! من نمی خوام کاربر بفهمه که چه اتفاقی داره میوفته.

the king
شنبه 23 آذر 1398, 17:29 عصر
با سپاس از شما،
بله با Run as admin مشکل حل میشه ولی من نمی خوام به کاربرم بگم که Run as admin بکنه! و مشکل دیگه اینکه اگر کاربر این کار را انجام نده، دات نت ارور میده و داخل ارور هم اسم فایل ها را مینویسه! من نمی خوام کاربر بفهمه که چه اتفاقی داره میوفته.

مورد اول اینکه سخت نگیرید، اگه کاربر از سایت مایکروسافت ابزار Process Monitor رو دانلود کرده باشه میتونه همیشه و در هر شرایطی بفهمه که چه اتفاقی داره میافته، چه دات نت پیامی نشون بده و چه نده. شما هر کاری که در برنامه تون موفق و غیر موفق بکنید Process Monitor میتونه نشون بده.

مورد دوم اینکه اگر برنامه تون برای اجرا نیاز به دسترسی سطح ادمین داره، این رو در مانیفیست پروژه تون مشخص کنید. حداقل کارکردش اینه که سیستم عامل میتونه بصورت پیشفرض از کاربر برای برنامه تون این سطح دسترسی رو درخواست کنه.
در منوی Project ویژوال استدیو گزینه ...Add New Item رو انتخاب کنید و بین گزینه ها Application Manifest File رو انتخاب کنید. در فایل app.manifest که به پروژه تون اضافه شده و باز میشه چند تا سطر requestedExecutionLevel> هستند که راهنما هستند و می توانید ازشون رد بشید و برسید به یک سطر requestedExecutionLevel> که فعال ئه و پیشفرض سطح level اش asInvoker ئه. سطح level اش رو مشابه راهنما از asInvoker تغییر بدید به requireAdministrator یا highestAvailable
دقت کنید که اون سطر های requestedExecutionLevel> پشت سر هم صرفا راهنما هستند و قرار نیست تغییر داده بشن.

مورد سوم اینه که اگر احتمال بروز خطا در عملیاتی هست، حتما با Try Catch End Try مهارش کنید تا اگر خطایی رخ داد خودتون تصمیم بگیرید که چه واکنشی نشون داده بشه.

autosystem
شنبه 23 آذر 1398, 19:52 عصر
مورد اول اینکه سخت نگیرید، اگه کاربر از سایت مایکروسافت ابزار Process Monitor رو دانلود کرده باشه میتونه همیشه و در هر شرایطی بفهمه که چه اتفاقی داره میافته، چه دات نت پیامی نشون بده و چه نده. شما هر کاری که در برنامه تون موفق و غیر موفق بکنید Process Monitor میتونه نشون بده.

مورد دوم اینکه اگر برنامه تون برای اجرا نیاز به دسترسی سطح ادمین داره، این رو در مانیفیست پروژه تون مشخص کنید. حداقل کارکردش اینه که سیستم عامل میتونه بصورت پیشفرض از کاربر برای برنامه تون این سطح دسترسی رو درخواست کنه.
در منوی Project ویژوال استدیو گزینه ...Add New Item رو انتخاب کنید و بین گزینه ها Application Manifest File رو انتخاب کنید. در فایل app.manifest که به پروژه تون اضافه شده و باز میشه چند تا سطر requestedExecutionLevel> هستند که راهنما هستند و می توانید ازشون رد بشید و برسید به یک سطر requestedExecutionLevel> که فعال ئه و پیشفرض سطح level اش asInvoker ئه. سطح level اش رو مشابه راهنما از asInvoker تغییر بدید به requireAdministrator یا highestAvailable
دقت کنید که اون سطر های requestedExecutionLevel> پشت سر هم صرفا راهنما هستند و قرار نیست تغییر داده بشن.

مورد سوم اینه که اگر احتمال بروز خطا در عملیاتی هست، حتما با Try Catch End Try مهارش کنید تا اگر خطایی رخ داد خودتون تصمیم بگیرید که چه واکنشی نشون داده بشه.

ممنون از توضیحات خوب و کامل شما، خوشبختانه با توضیحات شما مشکل من حل شد. یه سوال دیگه داشتم:
من از دستور IO.File.WriteAllBytes برای جایگزینی فایل های dll استفاده کردم. در واقع این دستور انگار که فایلها را patch میکنه و میره کدهای باینری فایلها را جایگزین میکنه. آیا این روش درست هست؟ یا اینکه روشی برای کپی مستقم فایلهایی که در my.resource ایمپورت شده اند در PC وجود دارد؟

the king
شنبه 23 آذر 1398, 20:31 عصر
ممنون از توضیحات خوب و کامل شما، خوشبختانه با توضیحات شما مشکل من حل شد. یه سوال دیگه داشتم:
من از دستور IO.File.WriteAllBytes برای جایگزینی فایل های dll استفاده کردم. در واقع این دستور انگار که فایلها را patch میکنه و میره کدهای باینری فایلها را جایگزین میکنه. آیا این روش درست هست؟ یا اینکه روشی برای کپی مستقم فایلهایی که در my.resource ایمپورت شده اند در PC وجود دارد؟

اتفاقا برای فایل ها و کلا داده هایی که شما در Resources پروژه تون دارید همون WriteAllBytes گزینه مناسبیه و من هم جز اون پیشنهادی ندارم.
داده هایی که شما در اون My.Resources دارید همون بایت های باینری است، دیگه فایل اولیه نیست، صرفا محتویات فایل ئه. اونها دیگه فایلی که Add کردید نیستند.
فایل اولیه اسم و پسوند داشت، تاریخ ایجاد داشت، تاریخ ویرایش داشت، صفاتی مثل Readonly و System و ... داشت و سطح دسترسی برای کاربران و غیره.
وقتی شما وارد My.Resources کردیدش دیگه همه این اطلاعات تکمیلی مربوط به فایل از دست رفته و دیگه ماهیت فایل نداره. شما فقط همون داده باینری رو دارید که باید توسط اونها یک فایل تولید کنید.
برای همین گزینه دیگری نیست.

autosystem
شنبه 23 آذر 1398, 20:47 عصر
اتفاقا برای فایل ها و کلا داده هایی که شما در Resources پروژه تون دارید همون WriteAllBytes گزینه مناسبیه و من هم جز اون پیشنهادی ندارم.
داده هایی که شما در اون My.Resources دارید همون بایت های باینری است، دیگه فایل اولیه نیست، صرفا محتویات فایل ئه. اونها دیگه فایلی که Add کردید نیستند.
فایل اولیه اسم و پسوند داشت، تاریخ ایجاد داشت، تاریخ ویرایش داشت، صفاتی مثل Readonly و System و ... داشت و سطح دسترسی برای کاربران و غیره.
وقتی شما وارد My.Resources کردیدش دیگه همه این اطلاعات تکمیلی مربوط به فایل از دست رفته و دیگه ماهیت فایل نداره. شما فقط همون داده باینری رو دارید که باید توسط اونها یک فایل تولید کنید.
برای همین گزینه دیگری نیست.
باز هم از توضیحات خوب و جامعتون ممنونم. یه سوال دیگه:
همونطور که گفتم من می خوام یک تعداد فایل DLL را در دایرکتوری یک نرم افزار نصب شده کپی کنم(شما فرض کنید مثلا در دایرکتوری نرم افزار فتوشاپ). سوالم اینه که با چه دستوری میتونم به مسیر دایرکتوری این نرم افزار دسترسی پیدا کنم؟ چون اگر من یک آدرس مطلق بدهم، ممکنه کاربر در درایوی غیر از درایو پیشفرض C نصب کرده باشه.

the king
شنبه 23 آذر 1398, 21:35 عصر
باز هم از توضیحات خوب و جامعتون ممنونم. یه سوال دیگه:
همونطور که گفتم من می خوام یک تعداد فایل DLL را در دایرکتوری یک نرم افزار نصب شده کپی کنم(شما فرض کنید مثلا در دایرکتوری نرم افزار فتوشاپ). سوالم اینه که با چه دستوری میتونم به مسیر دایرکتوری این نرم افزار دسترسی پیدا کنم؟ چون اگر من یک آدرس مطلق بدهم، ممکنه کاربر در درایوی غیر از درایو پیشفرض C نصب کرده باشه.
چند تا منبع برای پیدا کردن محل نصب نرم افزار هست، یکی تنظیمات Registry همون برنامه خاص، مثلا HKEY_LOCAL_MACHINE\SOFTWARE\Adobe :


HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Photoshop\110.0\ ApplicationPath
.
.
.
HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Photoshop\120.0\ ApplicationPath


منبع دیگه HKEY_CLASSES_ROOT\Applications ئه، البته صرفا برای برخی برنامه ها :


HKEY_CLASSES_ROOT\Applications\Photoshop.exe\shell \open\command


منبع دیگه جستجوی یک CLSID خاص ئه که از قبل میدونید مربوط به کلاسی از برنامه فلان ئه :


HKEY_CLASSES_ROOT\CLSID\{04581b80-0023-46f3-bb7b-b75313b05185}\LocalServer32


برای هر نرم افزاری با شرایط مختلفی میشه همچین کلید های Registry ای رو پیدا کرد و به ندرت لازم میشه سراغ فایل ها برید.

Imports Microsoft.Win32

Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Using key = Registry.LocalMachine.OpenSubKey("SOFTWARE\Adobe\Photoshop")
If key Is Nothing Then Exit Sub
Dim subkeys = key.GetSubKeyNames()
Array.Sort(subkeys)
For i = UBound(subkeys) To 0 Step -1
Using subKey = key.OpenSubKey(subkeys(i) & "\ApplicationPath")
If subKey IsNot Nothing AndAlso subKey.GetValue("") IsNot Nothing Then
TextBox1.Text = subKey.GetValue("")
Exit For
End If
End Using
Next
End Using
Catch
End Try
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
Using key = Registry.ClassesRoot.OpenSubKey("Applications\Photoshop.exe\shell\open\command")
If key IsNot Nothing AndAlso key.GetValue("") IsNot Nothing Then
Dim cmd = key.GetValue("").ToString()
TextBox2.Text = cmd.Substring(0, cmd.LastIndexOf("", StringComparison.Ordinal) + 1).TrimStart("""")
End If
End Using
Catch
End Try
End Sub

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Try
Using key = Registry.ClassesRoot.OpenSubKey("CLSID\{04581b80-0023-46f3-bb7b-b75313b05185}\LocalServer32")
If key IsNot Nothing AndAlso key.GetValue("") IsNot Nothing Then
Dim cmd = key.GetValue("").ToString()
TextBox3.Text = cmd.Substring(0, cmd.LastIndexOf("", StringComparison.Ordinal) + 1).TrimStart("""")
End If
End Using
Catch
End Try
End Sub
End Class

autosystem
شنبه 23 آذر 1398, 22:02 عصر
چند تا منبع برای پیدا کردن محل نصب نرم افزار هست، یکی تنظیمات Registry همون برنامه خاص، مثلا HKEY_LOCAL_MACHINE\SOFTWARE\Adobe :


HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Photoshop\110.0\ ApplicationPath
.
.
.
HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Photoshop\120.0\ ApplicationPath


منبع دیگه HKEY_CLASSES_ROOT\Applications ئه، البته صرفا برای برخی برنامه ها :


HKEY_CLASSES_ROOT\Applications\Photoshop.exe\shell \open\command


منبع دیگه جستجوی یک CLSID خاص ئه که از قبل میدونید مربوط به کلاسی از برنامه فلان ئه :


HKEY_CLASSES_ROOT\CLSID\{04581b80-0023-46f3-bb7b-b75313b05185}\LocalServer32


برای هر نرم افزاری با شرایط مختلفی میشه همچین کلید های Registry ای رو پیدا کرد و به ندرت لازم میشه سراغ فایل ها برید.

Imports Microsoft.Win32

Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Using key = Registry.LocalMachine.OpenSubKey("SOFTWARE\Adobe\Photoshop")
If key Is Nothing Then Exit Sub
Dim subkeys = key.GetSubKeyNames()
Array.Sort(subkeys)
For i = UBound(subkeys) To 0 Step -1
Using subKey = key.OpenSubKey(subkeys(i) & "\ApplicationPath")
If subKey IsNot Nothing AndAlso subKey.GetValue("") IsNot Nothing Then
TextBox1.Text = subKey.GetValue("")
Exit For
End If
End Using
Next
End Using
Catch
End Try
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
Using key = Registry.ClassesRoot.OpenSubKey("Applications\Photoshop.exe\shell\open\command")
If key IsNot Nothing AndAlso key.GetValue("") IsNot Nothing Then
Dim cmd = key.GetValue("").ToString()
TextBox2.Text = cmd.Substring(0, cmd.LastIndexOf("", StringComparison.Ordinal) + 1).TrimStart("""")
End If
End Using
Catch
End Try
End Sub

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Try
Using key = Registry.ClassesRoot.OpenSubKey("CLSID\{04581b80-0023-46f3-bb7b-b75313b05185}\LocalServer32")
If key IsNot Nothing AndAlso key.GetValue("") IsNot Nothing Then
Dim cmd = key.GetValue("").ToString()
TextBox3.Text = cmd.Substring(0, cmd.LastIndexOf("", StringComparison.Ordinal) + 1).TrimStart("""")
End If
End Using
Catch
End Try
End Sub
End Class

از طریق سرویس اون برنامه نمیشه محل نصب را پیدا کرد؟

the king
شنبه 23 آذر 1398, 22:20 عصر
از طریق سرویس اون برنامه نمیشه محل نصب را پیدا کرد؟

کدوم سرویس؟ Adobe {ApplicationName} Update Service و Adobe Genuine Software Integrity Service ؟
فتوشاپ تا جایی که میدونم سرویس خاصی نداره که مسیر نصب خودش باشه.
نمیدونم از اینها چی بشه درآورد جز مسیر نصب خود سرویس که اونم ربطی به محل نصب نرم افزاری مثل فتوشاپ نداره.
اگه نرم افزاری که دنبالش میگردید خودش سرویس باشه، فرضا Kaspersky Security Cloud، بله می توانید در HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\servic es مسیرش رو پیدا کنید وگرنه نه.

autosystem
شنبه 23 آذر 1398, 22:30 عصر
نرم افزاری که من دارم وقتی وارد Task Manager می شم و از سرویس پرویرتیز می گیرم مسیر فایل اون دقیقا داخل دایرکتری نرم افزار هست. من می خوام با دستوراتی مثل ServiceController مسیر نصب نرم افزار را پیدا کنم.

the king
شنبه 23 آذر 1398, 23:11 عصر
نرم افزاری که من دارم وقتی وارد Task Manager می شم و از سرویس پرویرتیز می گیرم مسیر فایل اون دقیقا داخل دایرکتری نرم افزار هست. من می خوام با دستوراتی مثل ServiceController مسیر نصب نرم افزار را پیدا کنم.

با ServiceController می توانید سرویس رو کنترل کنید، ولی اطلاعاتی مثل مسیر فایل اجرایی سرویس رو بهتون نمیده.
مسیر سرویس رو یا باید از Registry ویندوز بخونید یا از WMI ویندوز و یا از کتابخانه خاصی استفاده کنید.