الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مشكلة في GetCommandLine

مغلق
بدأه محمد حمود في 2 أكتوبر 2004 · 11 رد · 718 مشاهدة · في لغة Ms Visual Basic 6 وما قبلها من إصدارات
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

استخدمت تابع API التالي:

Declare Function GetCommandLine Lib "kernel32" Alias "GetCommandLineA" () As String

وذلك لكي أقرأ سطر الأوامر المرسل لبرنامجي، وفوجئت بظهور رسالة خطأ من الويندوز تشير إلى عدم إمكانية قراءة الذاكرة وذلك عند تنفيذ هذا السطر:

msgbox GetCommandLine

وقد جربت البرنامج على أكثر من جهاز وظهرت نفس المشكلة، علماً أن الأجهزة تحتوي ويندوز 2000 بروفيشنال، وفيجوال بيسك 6 مع سيرفيس باك 5.

هل من حل لهذه المشكلة؟

أمر آخر:

حاولت استخدام الأمر command الخاص بفيجوال بيسك كبديل عن تابع API السابق، ولكن ظهرت مشكلة جديدة، وهي أن هذا الأمر لايقبل أسماء الملفات الطويلة، فمثلاً يعيد لي المسار كمايلي:

c:\longfile~1.txt

أذكر أنني استخدمت هذه الأوامر سابقاً بدون مشاكل منذ وقت طويل، ولا أعرف مالذي يحصل الآن :-(

محمد حمود

ماجستير تقنية المعلومات

بكالوريوس هندسة مدنية

محترف إدارة مشاريع (PMP)

مهندس جودة البرمجيات (CSQE)

مبرمج معتمد من مايكروسوفت (MCP)

متخصص في نظم المعلومات الجغرافية GIS

mohamed.hammod(at)gmail.com

www.ShapeViewer.com

#2

السلام عليكم و رحمة الله و بركاته

جرب هذه ان شاء الله تصل الى ما تريد

        
    MessageBoxEx Me.hwnd, "The command line: " + GetCommLine, "Command Line ...", MB_ICONEXCLAMATION, 0
#3

Private Declare Function MessageBoxEx Lib "user32" Alias "MessageBoxExA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As Long, ByVal wLanguageId As Long) As Long

#4

السلام عليكم

اخي العزيز استخدم هذا الكود واعطيني رأيك .

ألصقه في الفورم دون تغيير ثم اصنع ملف تنفيذي EXE ثم مرر له الاوامر وسترى انه يطبعها علي الفورم .

Function GetCommandLine(Optional MaxArgs)
Dim C, CmdLine, CmdLnLen, InArg, I, NumArgs
If IsMissing(MaxArgs) Then
MaxArgs = 10
End If
ReDim ArgArray(MaxArgs)
NumArgs = 0:
InArg = False
CmdLine = Command()
CmdLnLen = Len(CmdLine)
For I = 1 To CmdLnLen
C = Mid(CmdLine, I, 1)
If (C <> " " And C <> vbTab) Then
If Not InArg Then
If NumArgs = MaxArgs Then
Exit For
End If
NumArgs = NumArgs + 1
InArg = True
End If
ArgArray(NumArgs) = ArgArray(NumArgs) & C
Else
InArg = False
End If
Next I
ReDim Preserve ArgArray(NumArgs)
GetCommandLine = ArgArray()
End Function


Private Sub Form_Activate()
Dim I
s = GetCommandLine
For I = 1 To UBound(s)
Print s(I)
Next I
End Sub

تحياتي لك Prof_1982

الإنسان الذي يقول بأنه لا يمكن عمل شيء يجب ألا يعيق مطلقاً الإنسان الذي يقوم بعمل ذلك الشيء.

إن تخطئ فأنت إنسان ... أما أن تلوم جهازك الكمبيوتر على خطأك فهذا أكثر إنسانية.

#5

شكراً لكما.

للأسف لم يتم حل المشكلة:

-بالنسبة للأخ محمد صادق: كودك أعطى نفس الخطأ.

-بالنسبة للأخ prof: الأمر command لايعطيني أسماء الملفات الطويلة بشكل صحيح وذلك إذا عملت association لنوع معين من الملفات مع برنامجي ثم شغلت البرنامج من خلال عمل double click على ملف من ذلك النوع.

أدعوكم إلى تجريب البرنامج المرفق، والذي يعطيني رسالة خطأ فور تشغيله:

comm_line.zip

تم تعديل هذه المشاركة بواسطة محمد حمود في 2 أكتوبر 2004 في 11:14

محمد حمود

ماجستير تقنية المعلومات

بكالوريوس هندسة مدنية

محترف إدارة مشاريع (PMP)

مهندس جودة البرمجيات (CSQE)

مبرمج معتمد من مايكروسوفت (MCP)

متخصص في نظم المعلومات الجغرافية GIS

mohamed.hammod(at)gmail.com

www.ShapeViewer.com

#6

عفواً على المثال السابق و هذا الكود الكامل

Const SHGFI_ICONLOCATION = &H1000
Const MB_ICONASTERISK = &H40&
Const MB_ICONEXCLAMATION = &H30&
Const MAX_PATH = 260
Private Type MSGBOXPARAMS
    cbSize As Long
    hwndOwner As Long
    hInstance As Long
    lpszText As String
    lpszCaption As String
    dwStyle As Long
    lpszIcon As String
    dwContextHelpId As Long
    lpfnMsgBoxCallback As Long
    dwLanguageId As Long
End Type
Private Declare Function GetLogicalDrives Lib "kernel32" () As Long
Private Declare Function MessageBoxEx Lib "user32" Alias "MessageBoxExA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As Long, ByVal wLanguageId As Long) As Long
Private Declare Function MessageBoxIndirect Lib "user32" Alias "MessageBoxIndirectA" (lpMsgBoxParams As MSGBOXPARAMS) As Long
Private Declare Sub PostQuitMessage Lib "user32" (ByVal nExitCode As Long)
Private Declare Function GetCommandLine Lib "kernel32" Alias "GetCommandLineA" () As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Sub Form_Paint()
    
    Dim MBP As MSGBOXPARAMS, LDs As Long, Cnt As Long, sDrives As String
    'get the available drives
    LDs = GetLogicalDrives
    sDrives = "Available drives:"
    For Cnt = 0 To 25
        If (LDs And 2 ^ Cnt) <> 0 Then
            sDrives = sDrives + " " + Chr$(65 + Cnt)
        End If
    Next Cnt
    'Show the commandline
    MessageBoxEx Me.hwnd, "The command line: " + GetCommLine, "Command Line ...", MB_ICONEXCLAMATION, 0
    'Set the structure size
    MBP.cbSize = Len(MBP)
    'Set the icon style
    MBP.dwStyle = MB_ICONASTERISK
    'set the owner wndow
    MBP.hwndOwner = Me.hwnd
    'set teh text
    MBP.lpszText = sDrives
    'set the caption
    MBP.lpszCaption = "Available drives"
    'Show the messagebox
    MessageBoxIndirect MBP
    'end our application
    PostQuitMessage 0
End Sub
Private Function GetCommLine() As String
    Dim RetStr As Long, SLen As Long
    Dim Buffer As String
    'Get a pointer to a string, which contains the command line
    RetStr = GetCommandLine
    'Get the length of that string
    SLen = lstrlen(RetStr)
    If SLen > 0 Then
        'Create a buffer
        GetCommLine = Space$(SLen)
        'Copy to the buffer
        CopyMemory ByVal GetCommLine, ByVal RetStr, SLen
    End If
End Function
#7

هذا الكود مبسط للكود السابق و شغال انا جربته أكثر من عشر مرات

Option Explicit
Const MB_ICONEXCLAMATION = &H30&
Private Declare Function MessageBoxEx Lib "user32" Alias "MessageBoxExA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As Long, ByVal wLanguageId As Long) As Long
Private Declare Function GetCommandLine Lib "kernel32" Alias "GetCommandLineA" () As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Private Sub Form_Load()
MessageBoxEx Me.hwnd, "The command line: " + GetCommLine, "Command Line ...", MB_ICONEXCLAMATION, 0
End Sub
Private Function GetCommLine() As String
   Dim RetStr As Long, SLen As Long
   Dim Buffer As String
   RetStr = GetCommandLine
   SLen = lstrlen(RetStr)
   If SLen > 0 Then
       'Create a buffer
       GetCommLine = Space$(SLen)
       'Copy to the buffer
       CopyMemory ByVal GetCommLine, ByVal RetStr, SLen
   End If
End Function

و اسف على الاطالة

comm_شغال.zip

تم تعديل هذه المشاركة بواسطة محمد صادق في 2 أكتوبر 2004 في 11:30

#8

شكراً جزيلاً للأخ محمد الصادق على جهده.

لقد عمل معي الكود الموجود في الملف الذي قمتَ بإرفاقه بشكل جيد.

وبالنسبة للأمر command فقد عمل معي أيضاً وأصبح يُظهر أسماء الملفات الطويلة بشكل صحيح، حيث كانت المشكلة هي في عملية ال Association في الريجستري.

ولكن هل قام أحد بتجريب الكود في الملف الذي أرفقته أنا سابقاً؟ وهل حصل معه نفس الخطأ؟ وماسبب ظهور ذلك الخطأ؟

نلاحظ أنني أنا استعملت تعريف تابع ال API كمايلي:

Private Declare Function GetCommandLine Lib "kernel32" Alias "GetCommandLineA" () As String

أي أنه يعيد قيمة string -وهذا الشكل لتعريف التابع موجود في API Viewer وفي غيره من ملفات المساعدة-

بينما كتبه الأخ محمد الصادق كمايلي:

Private Declare Function GetCommandLine Lib "kernel32" Alias "GetCommandLineA" () As Long

أي أنه يعيد القيمة Long

وبعد ذلك استخدم تابع copymemory.

فهل هو خطأ في ملفات التعليمات أم ماذا؟

محمد حمود

ماجستير تقنية المعلومات

بكالوريوس هندسة مدنية

محترف إدارة مشاريع (PMP)

مهندس جودة البرمجيات (CSQE)

مبرمج معتمد من مايكروسوفت (MCP)

متخصص في نظم المعلومات الجغرافية GIS

mohamed.hammod(at)gmail.com

www.ShapeViewer.com

#9

عفواً لا شكر على واجب

القيمة التي يرجعها تابع ال GetCommandLine هي تحتوي على مؤشر الذي يؤشر على مكان ال command line في الذاكرة و لقرائة محتويات الذاكرة التي يؤشر عليها نستخدم ال CopyMemory الذي هو يأخذ عنوان المكان و يرجع المحتوى

#10

حسناً، ولكن السؤال هو: لماذا إذاً تعريف التابع في API viewer مكتوب بشكل خاطئ؟

ولماذا توجد العديد من الأمثلة الخاطئة في الإنترنت مثل هذا:

http://www.vbcode.com/asp/showsn.asp?theID=3562

محمد حمود

ماجستير تقنية المعلومات

بكالوريوس هندسة مدنية

محترف إدارة مشاريع (PMP)

مهندس جودة البرمجيات (CSQE)

مبرمج معتمد من مايكروسوفت (MCP)

متخصص في نظم المعلومات الجغرافية GIS

mohamed.hammod(at)gmail.com

www.ShapeViewer.com

#11

أخي العزيز الجواب انه اصدار الجديد لهذا التابع يرجع القيمة Long و هو الذي يعمل على كل الويندوزات الجديدة منها و القديمة و لكن التابع الذي يرجع القيمة String لايعمل على الويندوزات الجديدة و يعمل على الويندوز 98 كما انه حضرتك تفضلت سابقاً كنت تحصل على جواب لان الويندوز كان قديم

------------------------------------------------

لا تنسونا من صالح دعائكم ....رمضان قريب

------------------------------------------------

تم تعديل هذه المشاركة بواسطة محمد صادق في 3 أكتوبر 2004 في 13:58

#12

عجبا ، جربت المثال عندي وضبط 100% مع الملفات الطويلة ، علي ويندوز XP

تم تعديل هذه المشاركة بواسطة prof_1982 في 3 أكتوبر 2004 في 23:24

الإنسان الذي يقول بأنه لا يمكن عمل شيء يجب ألا يعيق مطلقاً الإنسان الذي يقوم بعمل ذلك الشيء.

إن تخطئ فأنت إنسان ... أما أن تلوم جهازك الكمبيوتر على خطأك فهذا أكثر إنسانية.

هذا الموضوع مغلق.

مواضيع مشابهة