ตัวแก้ไขทรัพยากรคอนโซล: การแก้ไขทรัพยากรในไฟล์ EXE DLL

ทุกครั้งที่ฉันต้องสร้าง dll ทรัพยากรใหม่ ฉันจะเริ่มค้นหาอย่างเมามัน ข้อมูลที่จำเป็น- เบื่อแล้ว! ฉันจะใส่ทุกสิ่งที่ฉันคิดว่าสำคัญไว้ที่นี่

ด้วยการอนุญาตอย่างใจดีจาก Andrey Bushman ฉันจึงทำซ้ำได้เกือบทั้งหมด ฉันจะเสริมภาพหน้าจอที่ถ่ายจาก Andrey (เพื่อตัวฉันเองด้วย) ด้วยภาพหน้าจอจาก VS2015 CommunityEdition ความคิดเห็นของตัวเองฉันจะเขียนคำชี้แจงเป็นตัวเอียง
บทความนี้เขียนขึ้นสำหรับ AutoCAD 2009 แต่ใช้งานได้ดีกับ AutoCAD เวอร์ชันอื่นๆ

รูปภาพกราฟิกที่ใช้ในไฟล์ CUI สามารถนำมาจากไฟล์ BMP ภายนอกหรือจากไฟล์ทรัพยากร DLL ที่ไม่มีการจัดการซึ่งวางรูปภาพเหล่านี้ไว้ วิธีที่สองสะดวกกว่าในการใช้งาน ที่นี่เรามาดูวิธีการสร้างไฟล์ DLL ดังกล่าวและวิธีใช้ในไฟล์ CUI

AutoCAD มาเป็นเวลานาน (ตั้งแต่เวอร์ชัน 2010)ใช้รูปแบบ CUIX เป็น ไฟล์บางส่วนเมนูซึ่งก็คือ เก็บถาวรปกติซึ่งเปลี่ยนชื่อนามสกุลจาก ZIP เป็น CUIX อย่างไรก็ตาม บริษัท ของเราใช้ AutoCAD 2009 SP3 ซึ่งไม่สามารถทำงานกับ CUIX ได้ แต่ใช้รูปแบบเก่ากว่า - ไฟล์ CUI ซึ่งเนื้อหาจะแสดงในรูปแบบ XML

นอกจากนี้ตั้งแต่เวอร์ชัน 2015 ถ้าฉันจำไม่ผิด AutoCAD มีตัวเลือกการออกแบบสองตัวเลือกให้เลือก - ธีมสีเข้มและธีมสว่าง การสร้างไอคอนให้มองเห็นได้ทั้งสองที่นั้นเป็นเรื่องยากมาก และการเปลี่ยนชื่อภาพทันทีไม่ใช่สิ่งที่ดีที่สุด การตัดสินใจที่ดีที่สุด- รายละเอียดเพิ่มเติมด้านล่าง

การสร้างไฟล์ DLL ทรัพยากร

ใน MS วิชวลสตูดิโอ 2555 กำลังสร้าง โครงการใหม่ตามเทมเพลต Empty Project และกำหนดชื่อที่ต้องการ:

ตอนนี้อยู่ที่หน้าต่าง โซลูชัน Explorerกด คลิกขวาเลื่อนเมาส์ไปที่ชื่อโครงการและในเมนูบริบทที่ปรากฏขึ้นให้เลือกรายการ คุณสมบัติ- การกำหนดค่าที่ต้องการให้กับคุณสมบัติ ส่วนขยายเป้าหมายและ ประเภทการกำหนดค่า:

นอกจากนี้ในการตั้งค่าโครงการคุณต้องเปลี่ยนอีกหนึ่งตัวเลือก - ไม่มีจุดเริ่มต้น:

เมื่อทำการเปลี่ยนแปลงตามที่ระบุไว้ข้างต้นแล้ว ให้กดปุ่ม นำมาใช้และ ตกลง- ตอนนี้คุณสมบัติของโปรเจ็กต์ที่ยังว่างเปล่าของเราได้รับการกำหนดค่าอย่างถูกต้องแล้ว บนแท็บ โซลูชัน Explorer, จาก เมนูบริบทโครงการ ให้เลือกรายการ เพิ่ม -> รายการใหม่...และในกล่องโต้ตอบที่ปรากฏขึ้น ให้เลือกเทมเพลตไฟล์ทรัพยากร:

คุณสามารถกำหนดชื่อให้กับไฟล์ได้ในตัวอย่างของเรา ทรัพยากร rc- กดปุ่ม เพิ่ม- ไฟล์ที่เราเพิ่มจะมีรายการรูปภาพที่จะใช้ในไฟล์ CUI(x) ของเรา

Andrey แนะนำให้วางรูปภาพที่จะ "ขับเคลื่อน" ลงใน dll ไว้ในไดเร็กทอรีย่อย \images คำแนะนำที่สมเหตุสมผลอย่างสมบูรณ์ แม้ว่าจะไม่สำคัญก็ตาม อีกคำถามหนึ่งคือ ฉันขอแนะนำอย่างยิ่งให้คุณยังคงวางทรัพยากรเพื่อให้สามารถ "คำนวณ" ได้ เส้นทางสัมพัทธ์- ช่วยได้มากหากมีการพัฒนาในที่ทำงานมากกว่าหนึ่งแห่ง

เพื่อเป็นการทดลอง เรามาเพิ่มกัน ไฟล์บีเอ็มพี ขนาดที่แตกต่างกัน: 16x16, 24x24, 32x32, 48x48, 64x64 และ 128x128 ปุ่มบนจานสีเครื่องมือจะต้องมีรูปภาพขนาด 16x16 ในขณะที่ปุ่มที่วางบนจานสีริบบิ้นจะมีขนาดใหญ่กว่า ในไฟล์ CUI ทดสอบของเรา เราจะวางปุ่มที่มีความละเอียดด้านบนทั้งที่นี่และที่นั่นเพื่อดูผลลัพธ์ของการใช้ขนาดต่างๆ

ชี้แจง:ควรรับประกันว่า BMP จะโหลดเข้าสู่ VS ไม่ใช่สิ่งที่ดีที่สุดสำหรับผู้ใช้ GIMP ข่าวที่ดีที่สุด: ต้องสร้าง BMP ด้วยความลึกของสี 24 บิต และบันทึกโดยไม่มีการบีบอัด หากคุณไม่สามารถบันทึกโดยไม่บีบอัดได้ ให้ใช้ การแปลงชุดกับ โดยใช้โปรแกรม FastStone โปรแกรมดูรูปภาพคุณสามารถบรรลุผลตามที่ต้องการได้อย่างง่ายดาย

ก็เป็นไปได้ที่จะคัดลอกไฟล์ไปที่ รูปแบบ PNGอย่างไรก็ตาม AutoCAD 2009 ไม่สามารถใช้รูปภาพในรูปแบบนี้ในไฟล์ CUI

ชี้แจง: คุณสามารถลองเชื่อมต่อไม่ใช่ *.bmp แต่เป็นไฟล์ *.ico แน่นอนว่าบางส่วน งานพิเศษแต่มันเป็นไปได้
ในเวอร์ชันเก่า เพื่อให้แน่ใจว่าพื้นหลังมี "ความโปร่งใส" คุณควรใช้ สี RGB 192,192,192. AutoCAD เวอร์ชันเก่าถือว่าโปร่งใส
และนี่คืออีกสิ่งหนึ่ง - AutoCAD2018 ไม่ "เข้าใจ" bmp อีกต่อไปและเพียงแค่ต้องการ png

ตอนนี้กลับมาที่ IDE ของเรา: สลับไปที่แท็บ มุมมองทรัพยากร.

จากเมนูบริบทขององค์ประกอบ Resource.rc ให้เรียกรายการ เพิ่มทรัพยากร...

ในกล่องโต้ตอบ เพิ่มทรัพยากรในรายการ ประเภททรัพยากรเลือกองค์ประกอบ บิตแมป, กดปุ่ม นำเข้า...และระบุไฟล์ BMP จากไดเร็กทอรีย่อย \images ที่เราสร้างไว้ก่อนหน้านี้ เราได้รับผลลัพธ์ดังต่อไปนี้ (ลักษณะที่ปรากฏเหมือนกันทุกประการสำหรับทั้งปี 2555 และ 2558)

ตอนนี้ สำหรับแต่ละองค์ประกอบมูลค่าทรัพย์สิน บัตรประจำตัวประชาชนจำเป็นต้องแยกออกจากกัน เครื่องหมายคำพูดคู่เพื่อให้สามารถใช้งานได้สำเร็จในไฟล์ CUI(x) ของเรา:

เพียงเท่านี้ เรามารวบรวมไฟล์ DLL ของเรากันดีกว่า (ปุ่ม F6 หรือผ่านเมนู สร้าง -> สร้างโซลูชัน) .

สิ้นสุดใบเสนอราคา การดำเนินการเพิ่มเติมโดย การใช้ DLLฉันจะเขียนมันไว้ทีหลังถ้าฉันต้องการมัน

ตอนนี้มีบางอย่างจากประสบการณ์ของฉันเอง (และไม่ใช่แค่ของตัวเองเท่านั้น)

เทคโนโลยีนี้ใช้งานได้ดีเมื่อใช้ไฟล์ดัดแปลงบางส่วน หากคุณพยายามสร้าง dll ดังกล่าวสำหรับไฟล์ดัดแปลงขององค์กร คุณจะไม่สามารถแทนที่ dll ที่มีอยู่ได้: ขั้นแรกผู้ใช้ทุกคนจะต้องปิด AutoCAD

ชื่อ dll ต้องตรงกับชื่อไฟล์ cui(x) ขอแนะนำอย่างยิ่งให้วาง dll ไว้ข้างไฟล์ cui(x) ตามทฤษฎีแล้ว คุณสามารถโยนมันไปในเส้นทางการสนับสนุนได้ แต่โดยส่วนตัวแล้วฉันไม่เคยทำอะไรแบบนี้มาก่อน แล้วคุณจะเบื่อหน่ายกับการมองหามัน

เกี่ยวกับธีมต่างๆ ตามที่สัญญาไว้ ตามข้อมูลในฟอรัม ADN-CIS และความช่วยเหลือของ Autodesk:

  1. ใน AutoCAD เวอร์ชันที่ไม่มีธีม ทรัพยากรจะถูกพรากไปจาก dll ที่มีชื่อเดียวกับไฟล์ cui(x)
  2. ใน AutoCAD เวอร์ชันที่มีธีม คุณต้องสร้างทรัพยากร DLL แยกต่างหากสำหรับแต่ละธีม: สว่างและมืด ที่สอดคล้องกัน DLL ทรัพยากรใช้ขึ้นอยู่กับหัวข้อใด ตอนนี้นำไปใช้กับ หน้าจอผู้ใช้- หลักการตั้งชื่อสำหรับไฟล์ DLL กำหนดให้คุณต้องใช้ชื่อเดียวกันกับชื่อไฟล์การปรับแต่ง แต่คุณต้องเพิ่มส่วนต่อท้ายด้วย "_แสงสว่าง"สำหรับไฟล์ DLL ที่จะใช้เป็นธีมไลท์ เช่น หากคุณดาวน์โหลดไฟล์ CUIx ชื่อ mymenu.cuix, AutoCAD จะค้นหาไฟล์ไลบรารีทรัพยากร mymenu_light.dllหากใช้ธีมสีอ่อนและไฟล์ mymenu.dllหากใช้ธีมสีเข้ม

ลำดับของการรวบรวมห้องสมุดโดยคำนึงถึงตัวเลือกธีมได้รับการอธิบายอย่างสมบูรณ์แบบโดย Dmitry Zagorulkin:

ฉันสร้างไฟล์ CUIX เพียงอย่างเดียวในเวอร์ชัน 2014-2016 ไม่มีปัญหากับมัน นอกจากนี้ ฉันยังสร้างโปรเจ็กต์ C++ สองโปรเจ็กต์ที่มี DLL ไอคอนทรัพยากร - หนึ่งโปรเจ็กต์สำหรับดาร์กสคีม และโปรเจ็กต์ที่สองสำหรับโปรเจ็กต์สีอ่อน ในการตั้งค่าโครงการในส่วน "Build Events - Post Build Events" คุณสามารถกำหนดค่าเหตุการณ์เพื่อให้ไฟล์ dll ที่สร้างขึ้นถูกคัดลอกไปยังทันที โฟลเดอร์ที่จำเป็นภายใต้ ชื่อที่ถูกต้อง- ในโฟลเดอร์สำหรับเวอร์ชัน 2014 - เฉพาะ dll "light" ที่ไม่มีส่วนต่อท้ายในโฟลเดอร์สำหรับเวอร์ชัน 2015-2016 - "light" ที่มีส่วนต่อท้าย "_light", "dark" - โดยไม่มีส่วนต่อท้าย ฉันทำสิ่งนี้ในตอนแรก จากนั้นฉันก็กำหนดค่าสิ่งเดียวกัน แต่ในโปรเจ็กต์ตัวติดตั้ง WIX โดยทั่วไปไม่ว่าคุณจะดำเนินการอย่างไร คุณสามารถกำหนดค่าได้เพียงครั้งเดียว และไม่ต้องคิดว่าจะต้องคัดลอกไฟล์ที่ไหนและไฟล์ใด และจะตั้งชื่ออะไร - ทุกอย่างเสร็จสิ้นโดยอัตโนมัติ
AutoCAD กำหนดว่า DLL ใดที่จะโหลด:
- ในเวอร์ชันจนถึงปี 2014 จะมีการโหลดเฉพาะ DLL ที่มีไอคอนซึ่งมีชื่อตรงกับชื่อของไฟล์ CIUX เท่านั้น ตัวอย่างเช่น มีไฟล์: "MyTools.cuix" ไอคอนสำหรับไฟล์นี้จะถูกค้นหาในไฟล์ "MyTools.dll"
- ในเวอร์ชันปี 2558-2559 สำหรับโครงร่างสีเข้ม จะมีการโหลด DLL ที่ตรงกับชื่อ CUIX สำหรับโครงร่างสีอ่อน - ชื่อที่มีส่วนต่อท้าย "_light" ตัวอย่าง: "MyTools.cuix" ไอคอนสำหรับรูปแบบสีเข้ม: "MyTools.dll" สำหรับรูปแบบสีอ่อน: "MyTools_light.dll"
อีกจุดที่ไม่ชัดเจน คุณสามารถสร้างไฟล์ ICO หนึ่งไฟล์สำหรับไอคอนขนาด 16x16 และ 32x32 ในการดำเนินการนี้ คุณจะต้องวางรูปภาพสองรูปที่เกี่ยวข้องกันไว้ใน ICO ในการตั้งค่าปุ่ม จะมีการระบุ ID รูปภาพเดียวกันสำหรับปุ่มขนาดใหญ่และขนาดเล็ก AutoCAD จะเลือกไอคอนขึ้นอยู่กับขนาดของภาพที่ส่งออก เทคนิคนี้ช่วยให้คุณลดจำนวนลงได้อย่างมาก ไฟล์ ICOในทรัพยากรโปรเจ็กต์ C++

ว่าด้วยเรื่องการใช้ไฟล์ ico ทุกอย่างเป็นเรื่องง่ายที่นี่ - อ่านบทความการใช้ dll ทรัพยากรสำหรับ CUIx พร้อมแรสเตอร์แบบโปร่งใส พูดตามตรงฉันยังไม่ได้เล่นกับอะไรแบบนี้เลย แต่ฉันจะเชื่อดิมา
===
เพิ่ม:
คำพูดจากบทความเกี่ยวกับการเชื่อมต่อไฟล์ ico:

เพียงเพิ่มทรัพยากร ico ใหม่โดยใช้โปรแกรมแก้ไข Visual Studio และแก้ไขคุณสมบัติทรัพยากร “ICO” ใน “RCDATA” ดังที่แสดงด้านล่าง:

นอกเหนือจากการจัดเก็บทรัพยากรภายในไฟล์ .EXE แล้ว นักพัฒนา Delphi ยังสามารถสร้างไลบรารีแบบไดนามิกที่มีเฉพาะทรัพยากรเท่านั้น เรามาดูวิธีการทำเช่นนี้

ทรัพยากรอาจเป็นแบบมาตรฐานหรือที่ผู้ใช้กำหนด ข้อมูลในทรัพยากรมาตรฐานจะอธิบายไอคอน เคอร์เซอร์ เมนู กล่องโต้ตอบ บิตแมป เมตาไฟล์ที่ขยาย แบบอักษร ตารางปุ่มลัด สตริง และเวอร์ชัน ผู้ใช้กำหนดทรัพยากรสามารถมีข้อมูลใด ๆ ที่แอปพลิเคชันต้องการ (other.EXE, GIF, MP3 ฯลฯ )

ไลบรารีแบบไดนามิกประกอบด้วย รหัสทั่วไปหรือทรัพยากรที่สามารถแชร์ระหว่างหลายแอปพลิเคชันได้

การสร้าง DLL ด้วยทรัพยากร

ทำ DLLคุณต้องสร้างและคอมไพล์โปรเจ็กต์ว่างด้วยทรัพยากรเท่านั้น DLLซึ่งมีลิงก์ไปยังไฟล์ทรัพยากร .RESซึ่งมีทรัพยากรของคุณ

จากนั้นทำตามขั้นตอนเหล่านี้:

  1. สร้าง อาร์.ซี.ไฟล์ที่อธิบายทรัพยากรที่คุณต้องการใส่ DLL- ดังตัวอย่าง: ( ทรัพยากร adpdll- ชื่อ อาร์.ซี.ไฟล์ แอสกี) - หนึ่ง ไอคอนและหนึ่ง กิฟเพิ่มไปยัง อาร์.ซี.ไฟล์:
  2. adpdllresources.rc aboutlogo RCDATA aboutlogo.gif โรงงาน ICON FACTORY.ICO
  3. รวบรวม อาร์.ซี.ไฟล์ใน เรสไฟล์โดยใช้คอมไพเลอร์ทรัพยากร BRCC32
  4. สร้างโปรเจ็กต์ว่าง DLL- บันทึกเป็น adpResources.dpr- หลังจากเรียบเรียงแล้ว DLLจะมีชื่อ adpResources.dll. รหัสเต็มโครงการ DLLจะมีเพียงสี่บรรทัดในไฟล์เดียว
  5. ไลบรารี adpResources; ($R adpdllresources.RES) เริ่มต้นสิ้นสุด
  6. รวบรวมของคุณ DLL(ทำให้เเน่นอน adpdllresources.resอยู่ในไดเร็กทอรีเดียวกันกับโปรเจ็กต์ DLL

เร็ว ๆ นี้ DLLด้วยทรัพยากรจะถูกสร้างขึ้นคุณสามารถใช้มันภายในของคุณได้ แอพพลิเคชั่นเดลฟี- โปรดทราบว่าทรัพยากรเหล่านี้อยู่ภายใน DLLสามารถใช้แอปพลิเคชันใดก็ได้ (ไม่จำเป็นต้องเป็น Delphi)

วิธีการใช้ทรัพยากรจาก DLLs

เพื่อใช้ทรัพยากรจาก ไลบรารีแบบไดนามิกเพียงดาวน์โหลด DLLและทรัพยากรที่คุณต้องการใช้

ทำตามขั้นตอนเหล่านี้:

  1. สร้างอันใหม่ โครงการเดลฟี- ตามค่าเริ่มต้น Delphi จะเพิ่มหนึ่งแบบฟอร์มให้กับโปรเจ็กต์ บันทึกโครงการ
  2. สำเนา DLLด้วยทรัพยากร ( adpResources.dllไปยังโฟลเดอร์ที่บันทึกแอปพลิเคชันใหม่ของคุณไว้
  3. ดาวน์โหลดทรัพยากรตามด้านล่างนี้...

ตัวอย่างวิธีการอัพโหลดไอคอน โรงงานและวาดภาพบนผ้าใบ แบบฟอร์ม1, เมื่อไร Button1: TButton ถูกกด)

ขั้นตอน TForm1.Button1Click (ผู้ส่ง: TObject); const resICON = "โรงงาน"; var h: THandle; ไอคอน: HIcon; เริ่มต้น h:= LoadLibrary("adpResources.DLL"); ลองถ้า h 0 แล้วเริ่ม Icon:= LoadIcon(h, resICON); DrawIcon (Canvas.Handle, 10, 10, ไอคอน); สิ้นสุดอย่างอื่นเริ่มต้น ShowMessage ("โหลดทรัพยากร DLL ล้มเหลว!"); จบ;

ในที่สุด FreeLibrary (h); จบ; จบ; กิฟหากคุณเพิ่มการสนับสนุน กิฟคุณสามารถใช้ภาพ DLLเก็บไว้ในทรัพยากร

และวาดมันด้วย:

ขั้นตอน TForm1.Button2Click (ผู้ส่ง: TObject); const resGIF = "เกี่ยวกับโลโก้"; var h: THandle; กิฟ: TGifImage; ร:TRect; เริ่มต้น h:= LoadLibrary("adpResources.DLL"); ลองถ้า h 0 แล้วเริ่ม gif:= TGIFImage.Create; ลอง gif.LoadFromResourceName(h,resGIF); gif.Paint (แคนวาส, Form1.ClientRect, ); ในที่สุด gif.Free; จบ;


AutoCAD ใช้รูปแบบ CUIX เป็นไฟล์เมนูบางส่วนมานานแล้ว ซึ่งเป็นไฟล์เก็บถาวรทั่วไปที่มีการเปลี่ยนชื่อนามสกุลจาก ZIP เป็น CUIX อย่างไรก็ตาม บริษัท ของเราใช้ AutoCAD 2009 SP3 ซึ่งไม่สามารถทำงานกับ CUIX ได้ แต่ใช้รูปแบบเก่ากว่า - ไฟล์ CUI ซึ่งเนื้อหาจะแสดงในรูปแบบ XML

เกี่ยวกับเวอร์ชันของ AutoCAD และ MS Visual Studio (การพูดนอกเรื่องเล็กน้อยจากหัวข้อทั่วไป)

เพื่อที่จะเขียน ควบคุมปลั๊กอินสำหรับ AutoCAD คุณสามารถใช้ MS Visual Studio เวอร์ชันใดก็ได้ซึ่งมีความสามารถในการรวบรวมโค้ดที่ได้รับการจัดการสำหรับเวอร์ชันของแพลตฟอร์ม .NET (2.0, 3.0, 3.5, 4.0, 4.5) ที่ใช้ในเวอร์ชันของ AutoCAD ที่ สนใจเรา เวอร์ชันเป้าหมายของ .NET Framework แสดงอยู่ในรายการ ไฟล์การกำหนดค่า acad.exe.configและหากต้องการ เราก็สามารถมอบหมายใหม่ได้

สำหรับการเขียน ไม่สามารถควบคุมได้ปลั๊กอิน ARX ​​สำหรับ AutoCAD 2009 คุณสามารถใช้ MS Visual Studio เวอร์ชันใดก็ได้ แต่ต้องอยู่ภายใต้เงื่อนไขที่คอมพิวเตอร์มีเท่านั้น เวอร์ชันเครื่องมือสร้างซึ่งจำเป็นสำหรับ AutoCAD เวอร์ชันของคุณและเครื่องมือเหล่านี้มีให้ใช้งานใน IDE ของคุณ ตัวอย่างเช่นในการเขียนปลั๊กอิน ARX สำหรับ AutoCAD 2009 คุณต้องมีเวอร์ชันของเครื่องมือที่มีอยู่ใน MS Visual Studio 2005 ที่จริงแล้วคุณสามารถใช้ IDE ที่ระบุเวอร์ชันใหม่กว่าได้ โดยมีการระบุการตั้งค่าโครงการ รุ่นที่ต้องการเครื่องมือที่ควรใช้เมื่อสร้างโครงการ:


เพื่อให้รายการคุณสมบัติแบบเลื่อนลงไปที่ ชุดเครื่องมือแพลตฟอร์มมีชุดองค์ประกอบที่ให้คุณเลือกได้ เวอร์ชันที่ต้องการเครื่องมือต่างๆ จะต้องติดตั้งเครื่องมือเหล่านี้ไว้ล่วงหน้า เหล่านั้น. ต้องติดตั้ง MS Visual Studio ทุกรุ่นที่มีเครื่องมือที่คุณต้องการใช้ในการก่อสร้างบนคอมพิวเตอร์ของคุณในกรณีนี้ ปรากฎว่าคุณกำลังทำงานใน IDE ที่ใหม่กว่าจริง ๆ โดยใช้ข้อดีและความสะดวกของมัน และในเบื้องหลังโค้ดจะถูกรวบรวมโดยเครื่องมือของเวอร์ชันที่คุณระบุในการตั้งค่าโปรเจ็กต์ของคุณ

ควรติดตั้ง MS Visual Studio เวอร์ชันต่างๆ ตามลำดับโดยเริ่มจากเพิ่มเติม เวอร์ชั่นเก่าและปิดท้ายด้วยอันที่ใหม่กว่าเพื่อหลีกเลี่ยงความขัดแย้งประเภทต่างๆ หลังจากติดตั้ง IDE เวอร์ชันถัดไปแล้ว อย่าลืมติดตั้งแพ็คเกจการอัปเดต

ตามค่าเริ่มต้น MS Visual Studio 2012 "เห็น" และแสดงเฉพาะเครื่องมือจาก VS 2012, 2010 และ 2008 ในรายการดรอปดาวน์ชุดเครื่องมือแพลตฟอร์มเท่านั้น เพื่อให้ IDE เวอร์ชันเก่ากว่าแสดงในรายการ คุณต้องเรียกใช้ ใดๆ (เหล่านั้น. หนึ่งใน) จากการดำเนินการต่อไปนี้:

  • ติดตั้งแพ็คเกจ MSI โดยได้รับความอนุเคราะห์จาก Owen Wengard
  • ดำเนินการกำหนดค่าด้วยตนเองตามที่ระบุไว้
อย่างไรก็ตามเมื่อถึงเวลานั้น การสร้าง DLLรีซอร์สไฟล์ จากนั้นทุกอย่างจะง่ายกว่ามาก: เพียงคอมไพล์ไฟล์เพียงครั้งเดียว (โดยใช้เครื่องมือเวอร์ชันใดก็ได้) ด้วยการกำหนดค่า Release Win32 จากนั้นใช้งานบนแพลตฟอร์ม x86\x64 (ฉันคอมไพล์ x86 DLL และในเวลาเดียวกันใน Windows 7 x64 ไฟล์ CUI ของฉันดึงรูปภาพออกมาได้สำเร็จ)
การสร้างไฟล์ DLL ทรัพยากร

ใน MS Visual Studio 2012 ให้สร้างโปรเจ็กต์ใหม่โดยใช้เทมเพลต Empty Project และกำหนดชื่อที่ต้องการ:


ก่อนอื่นเราจะติดตั้งการกำหนดค่าใน Release Win32 ทันที:

ตอนนี้อยู่ที่หน้าต่าง โซลูชัน Explorerคลิกขวาที่ชื่อโครงการและเลือกรายการในเมนูบริบทที่ปรากฏขึ้น คุณสมบัติ- การกำหนดค่าที่ต้องการให้กับคุณสมบัติ ส่วนขยายเป้าหมายและ ประเภทการกำหนดค่า:



แม้ว่าไฟล์ DLL จะถูกสร้างขึ้นสำหรับ CUI ที่จะใช้ใน AutoCAD 2009 ในคุณสมบัติ ชุดเครื่องมือแพลตฟอร์มระบุเวอร์ชันแล้ว v110ซึ่งสอดคล้องกับ Visual Studio 2012 ไม่ใช่ v80(เครื่องมือ Visual Studio 2005) ซึ่งจำเป็นสำหรับการรวบรวมปลั๊กอิน ARX สำหรับ AutoCAD เวอร์ชันนี้


นอกจากนี้ในการตั้งค่าโครงการคุณต้องเปลี่ยนอีกหนึ่งตัวเลือก - ไม่มีจุดเข้า:


เมื่อทำการเปลี่ยนแปลงตามที่ระบุไว้ข้างต้นแล้ว ให้กดปุ่ม นำมาใช้และ ตกลง- ตอนนี้คุณสมบัติของโปรเจ็กต์ที่ยังว่างเปล่าของเราได้รับการกำหนดค่าอย่างถูกต้องแล้ว บนแท็บ โซลูชัน Explorerจากเมนูบริบทของโครงการ ให้เลือกรายการ เพิ่ม -> รายการใหม่... และในกล่องโต้ตอบที่ปรากฏขึ้น ให้เลือกเทมเพลตไฟล์ทรัพยากร:



คุณสามารถกำหนดชื่อให้กับไฟล์ได้ในตัวอย่างของเรา ทรัพยากร rc- กดปุ่ม เพิ่ม- ไฟล์ที่เราเพิ่มจะมีรายการรูปภาพที่จะใช้ในไฟล์ CUI ของเรา

ตอนนี้ในไดเรกทอรีโครงการของเรา เราจะสร้างไดเรกทอรีย่อยด้วยตนเองซึ่งเราจะคัดลอกไฟล์รูปภาพทั้งหมดที่เราต้องการเพิ่มลงในไฟล์ DLL ชื่อไดเร็กทอรีย่อยสามารถกำหนดได้ตามใจชอบเรียกมันว่า ภาพ- บนแท็บ โซลูชัน Explorerจากเมนูบริบทของโครงการ เลือกรายการ เปิดโฟลเดอร์ใน File Explorer:



ในหน้าต่าง Explorer ที่เปิดขึ้น ให้สร้างไดเรกทอรีย่อย ภาพและคัดลอกไฟล์ BMP ทั้งหมดที่เราต้องการลงไป

จากการทดลอง ให้เพิ่มไฟล์ BMP ที่มีขนาดต่างกัน: 16x16, 24x24, 32x32, 48x48, 64x64 และ 128x128 ปุ่มบนจานสีเครื่องมือต้องมีรูปภาพขนาด 16x16 ในขณะที่ปุ่มที่วางบนจานสีริบบิ้นจะมีขนาดใหญ่กว่า ในไฟล์ CUI ทดสอบของเรา เราจะวางปุ่มที่มีความละเอียดด้านบนทั้งที่นี่และที่นั่นเพื่อดูผลลัพธ์ของการใช้ขนาดต่างๆ

เป็นไปได้ที่จะคัดลอกไฟล์ในรูปแบบ PNG แต่ AutoCAD 2009 ไม่สามารถใช้รูปภาพในรูปแบบนี้ในไฟล์ CUI ตอนนี้กลับไปที่ IDE ของเรา: p สลับไปที่แท็บมุมมองทรัพยากร.



จากเมนูบริบทขององค์ประกอบ ทรัพยากร rcเรียกรายการ เพิ่มทรัพยากร...


ในกล่องโต้ตอบ เพิ่มทรัพยากรในรายการ ประเภททรัพยากรเลือกองค์ประกอบ บิตแมป, กดปุ่ม นำเข้า... และระบุไฟล์ BMP จากไดเร็กทอรีย่อยที่เราสร้างไว้ก่อนหน้านี้ ภาพ- เราได้รับผลลัพธ์ดังต่อไปนี้:


ตอนนี้ แต่ละค่าคุณสมบัติขององค์ประกอบ บัตรประจำตัวประชาชนต้องคั่นด้วยเครื่องหมายคำพูดคู่เพื่อให้สามารถใช้ในไฟล์ CUI ของเราได้สำเร็จ:


เพียงเท่านี้ เรามารวบรวมไฟล์ DLL ของเรากันดีกว่า:


ลองดูรายงานผลการรวบรวม:


และนี่คือ DLL ที่รอคอยมานานของเรา:

เราคัดลอกไฟล์ DLL ที่เป็นผลลัพธ์ไปยังไดเร็กทอรีเดียวกันกับที่เก็บไฟล์ CUI ของเรา และกำหนดชื่อเดียวกันให้กับพวกเขา: ทดสอบ.cuiและ test.dll- ขณะนี้ในไฟล์ CUI คุณสามารถใช้ไฟล์ DLL ของเราเป็นแหล่งที่มาของไอคอน BMP โดยกำหนดคำสั่งให้กับไฟล์ CUI ของเรา (ดูคุณสมบัติ รูปภาพขนาดเล็กและ ภาพใหญ่) จากนั้นมูลค่าทรัพย์สิน บัตรประจำตัวประชาชนซึ่งก่อนหน้านี้คั่นด้วยเครื่องหมายคำพูดคู่:


ไอคอนที่ระบุในคุณสมบัติ รูปภาพขนาดเล็กจะถูกใช้กับจานสี แถบเครื่องมือและสิ่งที่ระบุไว้สำหรับ ภาพใหญ่ -ใช้ใน ริบบิ้น.

โปรดทราบว่าบนแผงควบคุมของเรา แถบเครื่องมือบางส่วนทั้งหมดจะปรากฏขึ้น ภาพบีเอ็มพียกเว้นอันสุดท้าย - อันที่มีขนาด 128x128.

การสร้างไฟล์ dll

บ่อยครั้งในการทำงานของคุณคุณจะพบกับสถานการณ์เช่นนี้

คุณกำลังเผชิญกับงานคุณต้องเขียนโปรแกรม " ซุปเปอร์โน๊ตแพด"ซึ่งควรจะคงไว้ซึ่งฟังก์ชั่นทั้งหมด แผ่นจดบันทึกมาตรฐานแต่ในขณะเดียวกันก็มีฟังก์ชั่นเพิ่มเติมมากมายซึ่งเมื่อเลือกโปรแกรมสำหรับการทำงานกับข้อความผู้ใช้จะให้ความสำคัญกับโปรแกรมของคุณ ในการทำเช่นนี้มีการตัดสินใจที่จะเพิ่มฟังก์ชั่นใหม่หลายอย่างโดยหนึ่งในนั้นจะรับผิดชอบในการนับและแสดงจำนวนคำในข้อความ

สองสามสัปดาห์ต่อมา โปรแกรมก็ถูกเขียนขึ้น จากนั้นมันก็แพร่หลายสู่อินเทอร์เน็ต ผู้ใช้ก็ชื่นชมมัน ผลิตภัณฑ์ใหม่และเริ่มใช้มัน บรรลุเป้าหมายแล้ว

เวลาผ่านไปและคุณได้รับงานใหม่ให้เขียนโปรแกรม " สุดยอดนักแยกวิเคราะห์“หน้าที่หนึ่งของโปรแกรมนี้คือการนับคำในข้อความ คุณเข้าใจว่าคุณจะต้องพัฒนาวิธีการนับคำอีกครั้ง แต่ในขณะเดียวกันคุณก็จำได้ว่าไม่นานมานี้พวกเขาก็พัฒนาโปรแกรมขึ้นมา ที่ใช้ ฟังก์ชั่นนี้- เพื่อไม่ให้เกิดการสร้างวงล้อขึ้นใหม่ให้เปิดซอร์สโค้ดของโปรแกรม " ซุปเปอร์โน๊ตแพด"; และคัดลอกวิธีการทั้งหมดลงในซอร์สโค้ดของโปรแกรมใหม่" สุดยอดนักแยกวิเคราะห์" เยี่ยมเลย ตอนนี้คุณไม่ต้องเสียเวลาเขียนวิธีนี้อีกแล้ว และคุณสามารถอุทิศเวลาให้กับองค์ประกอบที่เหลือของโปรแกรมได้มากขึ้น แก้ไขปัญหาแล้ว

แต่จะเกิดอะไรขึ้นถ้าวิธีการนับคำไม่ได้เขียนโดยคุณ แต่โดยเพื่อนร่วมงานบางคนและด้วยเหตุผลบางอย่างคุณไม่สามารถเข้าถึงได้ รหัสแหล่งที่มาโปรแกรม " ซุปเปอร์โน๊ตแพด" นั่นคือตัวเลือกแรกที่คัดลอกวิธีการจากแหล่งที่มาจะไม่ทำงานและ วิธีนี้จะต้องเขียนเอง อืม เศร้า

แต่แล้วเพื่อนร่วมงานของคุณโทรหาคุณแล้วพูดว่า: ฉันจำได้ว่าตอนที่ฉันกำลังพัฒนาวิธีนี้ ฉันคิดว่าบางทีฉันอาจจะต้องใช้มันที่อื่น และด้วยเหตุนี้ฉันจึงตัดสินใจแยกมันออกจากชุดประกอบที่แยกจากกัน รูปแบบของไฟล์ไลบรารีแบบไดนามิก (dll) เพียงคัดลอกไฟล์นี้ dllในโครงการของคุณและเชื่อมต่อเป็นชุดประกอบภายนอก หลังจากนั้นคุณจะสามารถเข้าถึงวิธีการของฉันและจะสามารถใช้งานได้

ยอดเยี่ยม! คุณดำเนินการตามที่อธิบายไว้ทั้งหมดในโปรแกรม “ สุดยอดนักแยกวิเคราะห์” ปรากฏขึ้น วิธีที่ต้องการปัญหาได้รับการแก้ไขแล้วและคุณไม่จำเป็นต้องเขียนโค้ดใหม่ด้วยตนเองอีกต่อไป

นี่เป็นการสรุปคำพูดและตอนนี้เราไปสู่การศึกษาที่มีรายละเอียดมากขึ้น

DLL คืออะไร

DLL(ไลบรารีลิงก์แบบไดนามิก) คือไลบรารีลิงก์แบบไดนามิกหรือเรียกสั้น ๆ ว่าไลบรารีลิงก์แบบไดนามิก

อย่างที่ฉันเขียนไว้ก่อนหน้านี้ ไลบรารีแบบไดนามิกช่วยให้คุณสามารถนำโค้ดที่เขียนไว้ก่อนหน้านี้กลับมาใช้ใหม่ได้ และยังช่วยให้สามารถเคลื่อนย้ายโค้ดได้ดีขึ้นอีกด้วย การโอนไฟล์ไปยังแฟลชไดรฟ์ก็เพียงพอแล้วหรือ ดาวน์โหลด dllจากอินเทอร์เน็ต จากนั้นเพิ่มลงในโปรเจ็กต์ปัจจุบันและรับชุดฟังก์ชันเพิ่มเติมต่างๆ สำหรับแอปพลิเคชันของคุณทันที มันก็คุ้มค่าที่จะรู้ว่าในหนึ่งเดียว ไฟล์ dllสามารถจัดเก็บประเภท สมาชิก และเนมสเปซได้จำนวนเท่าใดก็ได้

การสร้างไฟล์ dll

ก่อนอื่นเรามาเลือกประเภทของใหม่กัน แอปพลิเคชันที่ถูกสร้างขึ้นหรือค่อนข้างเป็นโครงการ

เลือก ห้องสมุดชั้นเรียนนั่นคือเราสร้างไฟล์ไลบรารีแบบไดนามิก (dll)

คุณยังสามารถระบุเวอร์ชันของ Framework ที่จะสร้างขึ้นสำหรับโปรเจ็กต์นี้ได้

หลังจากที่ Visual Studio สร้างโครงร่างโครงการแล้ว คุณจะเห็นสิ่งต่อไปนี้:

นี่คือลักษณะของหน้าต่าง Solution Explorer

และก็จะหน้าตาประมาณนี้ พื้นที่ทำงานที่คุณมักจะเขียนโค้ดโปรแกรม

ดังนั้นเนมสเปซจึงได้รับ: รถยนต์และคลาส: Class1 Class1 ไม่ใช่ชื่อที่ดี มาเปลี่ยนโค้ดกันสักหน่อย โดยแทนที่ Class1 ด้วย BMW และเพิ่มวิธีการที่จะพิมพ์ชื่อของคลาสของเรา

และตอนนี้ก็จำเป็นต้องคอมไพล์เพื่อให้ได้แอสเซมบลี
หากคุณลองกด F5 หรือ Ctrl+F5 คุณจะเห็นหน้าต่างนี้


ข้อผิดพลาดนี้บ่งชี้เพียงว่ามีการสร้างไฟล์ไลบรารีแบบไดนามิก ( dll) แทนที่จะเป็นไฟล์ปฏิบัติการ (exe) ซึ่งไม่สามารถเรียกใช้ได้

หากต้องการคอมไพล์โปรเจ็กต์ ให้กดปุ่ม F6 หลังจากนั้นไฟล์ Car.dll จะปรากฏในไดเร็กทอรี bin\Debug

หากต้องการตรวจสอบว่าไฟล์ไลบรารีถูกสร้างขึ้นหรือไม่ ให้ใช้ปุ่ม แสดงไฟล์ทั้งหมดบนแท็บ Solution Explorer

สร้างแอสเซมบลีในรูปแบบของไฟล์ไลบรารีแบบไดนามิกได้สำเร็จแล้ว

ตอนนี้ไปที่โฟลเดอร์ bin\Debug เพื่อย้ายไปยังไดเร็กทอรีโปรเจ็กต์ปัจจุบันอย่างรวดเร็ว ใน Solution Explorer เดียวกัน ให้ใช้ไอเท็ม เปิดโฟลเดอร์ใน Windows Explorer

คัดลอกไฟล์แอสเซมบลีผลลัพธ์ (ในกรณีของเราคือไฟล์ Car.dll) ไปยังโฟลเดอร์ชั่วคราวบางโฟลเดอร์ ที่จริงแล้วไม่จำเป็นต้องทำเช่นนี้คุณสามารถออกไปได้ ไฟล์นี้ในโฟลเดอร์นี้ แต่เพื่อความสะดวก เรามาสร้างกัน แฟ้มใหม่และวางไฟล์ไลบรารีที่สร้างขึ้นไว้ที่นั่น

จากนั้นเราจะปิดโปรเจ็กต์ปัจจุบันและสร้างโปรเจ็กต์ใหม่ แต่คราวนี้เราจะเลือกประเภทโปรเจ็กต์ - แอปพลิเคชันคอนโซล

เรามาสร้างโครงการใหม่กันเถอะ

มีการสร้างโครงการใหม่แล้ว ตอนนี้เรามาเชื่อมต่อไลบรารีของเรา (Car.dll) กับโปรเจ็กต์ปัจจุบัน

กำลังเชื่อมต่อ dll

เมื่อต้องการทำเช่นนี้ในโฟลเดอร์ อ้างอิงในหน้าต่าง Solution Explorer คุณต้องคลิกขวาและเลือกเพิ่มการอ้างอิง หน้าต่างนี้จะเปิดขึ้น:

  1. เลือกแท็บเรียกดู
  2. ระบุโฟลเดอร์ที่มีไฟล์ไลบรารีที่สร้างขึ้น (ในตัวอย่างของเรา - Car.dll)
  3. เลือกไฟล์ ห้องสมุดที่ต้องการและกดปุ่ม ตกลง;
หากทุกอย่างถูกต้องคุณจะเห็นภาพต่อไปนี้

มันแสดงให้เห็นว่าลิงก์ไปยังแอสเซมบลี Car.dll ของเราซึ่งจัดเก็บรหัส IL ของเราถูกเพิ่มลงในโปรเจ็กต์ปัจจุบันของเราสำเร็จแล้ว ฉันหวังว่าคุณจะจำได้ว่าหลังจากการคอมไพล์แล้ว โค้ดทั้งหมดที่คุณเขียนจะถูกแปลงเป็นโค้ดระดับกลางใน IL (CIL, MSIL - นี่คือสิ่งเดียวกัน) คุณยังสามารถดูได้ว่าสำเนาไลบรารีของเราถูกวางไว้ในโฟลเดอร์ bin\Debug

หากจู่ๆ คุณลืมว่าเนมสเปซ ประเภท หรือสมาชิกใดในไลบรารีที่คุณสร้างขึ้นมี คุณสามารถใช้เครื่องมือ Visual Studio ได้ตลอดเวลา เบราว์เซอร์วัตถุ- หากต้องการทำสิ่งนี้ ให้ไปที่แท็บ Solution Explorer เปิดโฟลเดอร์ References และเพียงคลิกขวาที่ไลบรารีที่คุณเพิ่มไว้ก่อนหน้านี้ ในกรณีของเรา ฉันขอเตือนคุณ - นี่คือไฟล์ (Car.dll) และเลือก ดูในเบราว์เซอร์วัตถุจะปรากฏหน้าต่างลักษณะนี้ขึ้นมา

ในหน้าต่าง Object Browser คุณสามารถดูเนื้อหาของแอสเซมบลีของเราได้

เชื่อมต่อแอสเซมบลีแล้วและตอนนี้คุณสามารถทำงานกับเนื้อหาได้ ต่อไป มาทำขั้นตอนเสริมให้เสร็จสิ้น

มาเพิ่มการใช้กัน คำสำคัญโดยใช้เนมสเปซ Car จากไลบรารี Car.dll ที่เราสร้างขึ้น หลังจากนั้นเราจะสร้างอ็อบเจ็กต์ของคลาส BMW และดำเนินการเมธอด Output_Class_Name()

ผลลัพธ์:

ทุกอย่างทำงานได้

และอีกครั้งตามลำดับ:

  1. สร้างไฟล์ไดนามิกไลบรารี (dll)
  2. การเชื่อมต่อคอส ห้องสมุดนี้ไปยังโครงการของเราโดยการเพิ่มลิงก์ไปยังไฟล์ dll ของเราไปยังโฟลเดอร์ References
  3. (ไม่บังคับ) เราเชื่อมต่อเนมสเปซจากชุดประกอบที่เชื่อมต่อโดยใช้คำหลักที่ใช้ หรือใช้ชื่อเต็มนั่นคือ Namespace.Type (Car.BMW)
  4. กำไร
สี่ขั้นตอนนี้จะช่วยคุณได้ สร้าง ไลบรารี dll และเชื่อมต่อกับโครงการของคุณ

และในตอนท้ายก็ไม่มีข้อมูลมากนักเกี่ยวกับประเภทการประกอบ:

แอสเซมบลีมีประเภทหลัก ๆ ดังต่อไปนี้: ทั่วไปและส่วนตัว

การชุมนุมส่วนตัว

ไฟล์เหล่านี้เป็นไฟล์ไลบรารี เช่นเดียวกับไฟล์ Car.dll ที่เราสร้างไว้ก่อนหน้านี้ ซึ่งมีอยู่ในไดเร็กทอรีตลอดเวลา แอปพลิเคชันปัจจุบันหรือไดเร็กทอรีย่อยใดๆ

กลับไปที่จุดเริ่มต้นของบทความ

หลังจากสร้างแอปพลิเคชัน “Super Parser” แล้ว เราได้รับแอสเซมบลีในรูปแบบไฟล์ (exe) จากนั้นเราก็ตัดสินใจทดสอบโปรแกรมของเราและมอบให้เพื่อนของเรา ในขณะที่คุณยังบอกด้วยว่าถ้าเขาต้องการจะมี ฟังก์ชั่นเพิ่มเติมในโปรแกรมแล้วเขาก็แค่ต้องการอยู่ข้างๆ ไฟล์ exeวางไฟล์ไลบรารี Car.dll หลังจากนั้นเขาจะสามารถนับคำในข้อความได้ นั่นคือไลบรารีจะถูกจัดเก็บไว้ในไดเร็กทอรีเดียวกันกับไฟล์ปฏิบัติการ

การชุมนุมที่ใช้ร่วมกัน

เหล่านี้เป็นชุดประกอบที่ออกแบบมาสำหรับการใช้งานหลายครั้ง การใช้งานที่แตกต่างกันติดตั้งบนคอมพิวเตอร์เครื่องหนึ่ง

เช่น เรามีสองโปรแกรม ไฟล์ Car.dll ของเราที่จะใช้ เพื่อไม่ให้ Copy ไฟล์นี้ลงแต่ละโฟลเดอร์ เราสามารถวางไว้ในตำแหน่งพิเศษที่เรียกว่า Global Assembly Cache - (GAC) หรือ Global Assembly Cache ตอนนี้แอสเซมบลีจะถูกจัดเก็บไว้ในที่พิเศษแห่งเดียว และโปรแกรมของคุณจะรู้อยู่เสมอว่าจะค้นหาโค้ดไลบรารี่นี้ได้ที่ไหน หากเราใช้วิธีส่วนตัว เราจะต้องวางไลบรารีของเราไว้ในแต่ละโฟลเดอร์ของแอปพลิเคชันที่ควรโต้ตอบด้วย

การสร้าง DLL ที่มีทรัพยากรเท่านั้น

ไฟล์ทรัพยากรจะต้องได้รับการคอมไพล์ - "rc MyResDll.rc" - และแปลงโดยตัวเชื่อมโยงเป็น DLL ตรวจสอบให้แน่ใจว่าได้ระบุแฟล็ก "/NOENTRY" เนื่องจากไลบรารีแบบไดนามิกนี้มีเพียงทรัพยากรเดียวเท่านั้น และไม่ใช่บรรทัดของโค้ด: " ลิงค์ MyRedDll.res /DLL / NOENTRY"

ใน Visual Studio สิ่งนี้ทำได้ง่ายกว่า - เพียงคลิกที่โฟลเดอร์ "ทรัพยากร" ใน "หน้าต่าง" มุมมองไฟล์" และเพิ่ม ไฟล์ใหม่ทรัพยากรซึ่งสามารถแก้ไขได้ โปรแกรมแก้ไขภาพขึ้นอยู่กับดุลยพินิจของคุณเอง

โดยหลักการแล้ว หากต้องการโหลดทรัพยากรจาก DLL คุณสามารถใช้ฟังก์ชัน LoadLibray ที่เราคุ้นเคยอยู่แล้ว และส่งผ่านตัวอธิบาย LoadString ที่ส่งคืนมาหรือฟังก์ชันอื่นที่ทำงานกับทรัพยากร อย่างไรก็ตาม การโหลดไลบรารีแบบไดนามิกสามารถเร่งความเร็วได้อย่างมากหากเรา "อธิบาย" กับระบบว่า DLL นี้ไม่มีอะไรนอกจากทรัพยากร และเราเพียงแค่ต้องฉายมันลงในพื้นที่ที่อยู่ของกระบวนการ และเราสามารถดูแลทุกสิ่งทุกอย่างได้ด้วยตัวเอง .

นี่คือจุดที่ฟังก์ชัน LoadLibraryEx มีประโยชน์: อาร์กิวเมนต์แรก เช่นเดียวกับเพื่อนร่วมงาน LoadLibrary ระบุชื่อของไดนามิกไลบรารีที่จะโหลด ส่วนที่สองถูกสงวนไว้และจะต้องเป็น เท่ากับศูนย์และอันที่สามซึ่งเท่ากับ LOAD_LIBRARY_AS_DATAFILE บังคับให้ฟังก์ชันทำสิ่งที่เราต้องการ - โหลด DLL เป็นฐานข้อมูล (หากไลบรารีไดนามิกมีโค้ดนอกเหนือจากทรัพยากรด้วย การโหลดด้วยคีย์นี้ยังคงสำเร็จ แต่ ฟังก์ชั่นของ DLL ที่โหลดจะไม่พร้อมใช้งาน - ทรัพยากรเท่านั้น):

#รวม

#รวม

h=LoadLibraryEx("MyResDll.dll",0,

LOAD_LIBRARY_AS_DATAFILE);

LoadString(h,1,&buf,99);

printf("%s\n",&buf);

การสาธิตการโหลด DLL ที่ปรับให้เหมาะสมซึ่งไม่มีอะไรนอกจากทรัพยากร

โปรแกรมนี้คอมไพล์ในลักษณะเดียวกับตัวอย่างก่อนหน้าของการเชื่อมโยงอย่างชัดเจน - และเมื่อรัน จะแสดง "Hello, Word!" บนหน้าจออย่างมีชัย เพื่อยืนยันว่าทรัพยากร "string" จากไลบรารีลิงก์แบบไดนามิกได้รับการโหลดสำเร็จแล้ว! ในทำนองเดียวกัน คุณสามารถดาวน์โหลดทรัพยากรได้จาก ไฟล์ปฏิบัติการ- จากมุมมองนี้ พวกมันก็ไม่ต่างจากไดนามิกไลบรารี

OOP และ DLL

#รวม "stdafx.h"

DWORD ul_reason_for_call,

LPVOID lp สงวนไว้

//รหัสของเรา.

//เพิ่มฟังก์ชันเพิ่ม

ถ้า(a>b) res = a; อื่น ๆ = b;

อาจารย์สร้างเทมเพลตสำหรับ dll ของเราให้เรา เราจะพัฒนามัน เมื่อต้องการทำเช่นนี้ ให้เพิ่ม 1 ฟังก์ชันและ 1 คลาสพร้อมเมธอด นี่คือรหัส:

#รวม "stdafx.h"

BOOL APIENTRY DllMain (จัดการ hModule,

DWORD ul_reason_for_call,

LPVOID lp สงวนไว้

//รหัสของเรา.

//เพิ่มฟังก์ชันเพิ่ม

Declspec (dllexport) int เพิ่ม (int a, int b)

//เพิ่มคลาส MyClass ด้วยเมธอด MyMax

Declspec(dllexport) int MyMax(int ​​​​a, int b)(

ถ้า(a>b) res = a; อื่น ๆ = b;

โปรดทราบว่าเมื่อเพิ่มฟังก์ชันและเมธอดที่เราต้องการเรียกใช้จากภายนอก คุณจะต้องเขียนฟังก์ชันและเมธอดเหล่านั้นด้วยตัวแก้ไข __declspec(dllexport) วิธีนี้เราจะทำเครื่องหมายสิ่งที่เรียกว่าฟังก์ชันที่ส่งออก

มาคอมไพล์โปรแกรมกัน ไฟล์ firstdll.dll ควรปรากฏในโฟลเดอร์ดีบักของโครงการ

ตอนนี้เราเขียนโปรแกรมทดสอบ

#รวม

//รวมไฟล์ส่วนหัวที่จำเป็น

#include "..\firstdll.cpp"

ศาล<

ศาล<

มาเปิดโปรแกรมกันเถอะ อย่างที่คุณคาดหวัง มันจะพิมพ์ 22 และ 11

ฟังก์ชัน DllMain

DLL ส่วนใหญ่เป็นเพียงคอลเลกชันของฟังก์ชันอิสระที่สำคัญซึ่งจะถูกส่งออกไปยังและใช้งานโดยแอปพลิเคชัน นอกเหนือจากฟังก์ชันที่มีไว้สำหรับการส่งออกแล้ว DLL ทุกตัวยังมีฟังก์ชัน DllMain ฟังก์ชันนี้ออกแบบมาเพื่อเริ่มต้นและล้าง DLL โดยจะแทนที่ฟีเจอร์ LibMain และ WEP ที่พบใน Windows เวอร์ชันก่อนหน้า โครงสร้างของฟังก์ชัน DllMain ที่ง่ายที่สุดอาจมีลักษณะดังนี้:

BOOL WINAPI DllMain (จัดการ hInst, DWORD dwReason, LPVOID IpReserved) (

BOOL bAllWentWell=TRUE;

สวิตช์ (dwReason) (

กรณี DLL_PROCESS_ATTACH: // การเริ่มต้นกระบวนการ

case DLL_THREAD_ATTACH: // เตรียมใช้งานเธรด

case DLL_THREAD_DETACH: // ล้างโครงสร้างเธรด

case DLL_PROCESS_DETACH: // ทำความสะอาดโครงสร้างกระบวนการ

ถ้า (bAllWentWell) ส่งคืน TRUE;

มิฉะนั้นจะส่งคืน FALSE;

ฟังก์ชัน DllMain ถูกเรียกในหลายกรณี เหตุผลในการเรียกจะถูกกำหนดโดยพารามิเตอร์ dwReason ซึ่งสามารถรับค่าใดค่าหนึ่งต่อไปนี้

ในครั้งแรกที่กระบวนการโหลด DLL ฟังก์ชัน DllMain จะถูกเรียกด้วย dwReason เท่ากับ DLL_PROCESS_ATTACH ทุกครั้งที่กระบวนการสร้างเธรดใหม่ DllMain จะถูกเรียกด้วย dwReason เท่ากับ DLL_THREAD_ATTACH (ยกเว้นเธรดแรก เนื่องจากในกรณีนี้ dwReason จะเท่ากับ DLL_PROCESS_ATTACH)

เมื่อกระบวนการเสร็จสิ้นการทำงานกับ DLL ฟังก์ชัน DllMain จะถูกเรียกพร้อมกับพารามิเตอร์ dwReason เท่ากับ DLL_PROCESS_DETACH เมื่อเธรดถูกทำลาย (ยกเว้นอันแรก) dwReason จะเท่ากับ DLL_THREAD_DETACH

การดำเนินการเริ่มต้นและการล้างข้อมูลทั้งหมดสำหรับกระบวนการและเธรดที่ DLL ต้องการจะต้องดำเนินการตามค่า dwReason ดังที่แสดงในตัวอย่างก่อนหน้านี้ โดยทั่วไปการเริ่มต้นกระบวนการจะจำกัดอยู่ที่การจัดสรรทรัพยากรที่ใช้ร่วมกันระหว่างเธรด เช่น การโหลดไฟล์ที่แชร์ และการเริ่มต้นไลบรารี การเริ่มต้นเธรดใช้เพื่อกำหนดค่าโหมดเฉพาะสำหรับเธรดที่กำหนดเท่านั้น เช่น เพื่อเตรียมใช้งานหน่วยความจำภายในเครื่อง

DLL สามารถประกอบด้วยทรัพยากรที่แอปพลิเคชันที่เรียกใช้ไม่ได้เป็นเจ้าของ หากฟังก์ชัน DLL ทำงานบนทรัพยากร DLL จะเป็นประโยชน์อย่างมากในการจัดเก็บตัวจัดการ hInst ไว้ที่ใดที่หนึ่งให้พ้นทาง และใช้เมื่อโหลดทรัพยากรจาก DLL ตัวชี้ IpReserved ถูกสงวนไว้สำหรับการใช้งาน Windows ภายใน ดังนั้นจึงไม่ควรอ้างสิทธิ์ในใบสมัคร คุณสามารถตรวจสอบความหมายเท่านั้น ถ้า DLL ถูกโหลดแบบไดนามิก มันจะเป็นโมฆะ เมื่อโหลดแบบคงที่ ตัวชี้นี้จะไม่เป็นศูนย์

หากสำเร็จ ฟังก์ชัน DllMain จะต้องส่งคืน TRUE หากมีข้อผิดพลาดเกิดขึ้น FALSE จะถูกส่งกลับ และการดำเนินการเพิ่มเติมจะสิ้นสุดลง

ความคิดเห็น หากคุณไม่ได้เขียนฟังก์ชัน DllMain() ของคุณเอง คอมไพเลอร์จะใช้เวอร์ชันมาตรฐาน ซึ่งจะคืนค่า TRUE เพียงอย่างเดียว

ปัญหาตัวอย่าง:

จัดการ hThread; DWORD dwThreadId;

สวิตช์ (fdwเหตุผล)

กรณี DLL_PROCESS_ATTACH:

// DLL ถูกแมปกับพื้นที่ที่อยู่ของกระบวนการ

// สร้างเธรดเพื่อทำงานบางอย่าง

hThread = CreateThread(NULL, 0, บางฟังก์ชัน, NULL, 0, &dwThreadId);

// เลื่อนเธรดของเราจนกว่าเธรดใหม่จะเสร็จสมบูรณ์

WaitForSingleObject(hThread, INFINITE);

// ไม่จำเป็นต้องเข้าถึงเธรดใหม่อีกต่อไป

CloseHandle(hThread);

กรณี DLL_THREAD_ATTACH:

// มีการสร้างเธรดอื่นแล้ว

กรณี DLL_THREAD_DETACH:

// เธรดยุติอย่างถูกต้อง

กรณี DLL_PROCESS_DETACH:

// DLL ถูกยกเลิกการโหลดจากพื้นที่ที่อยู่ของกระบวนการ

ฟังก์ชันจุดเข้าใช้งานควรดำเนินการเริ่มต้นอย่างง่ายเท่านั้น พวกเขาไม่ควรเรียกใช้ฟังก์ชัน LoadLibrary หรือ LoadLibraryEx (หรือฟังก์ชันที่เรียกใช้ฟังก์ชันเหล่านี้) เนื่องจากสามารถสร้างลูปการขึ้นต่อกันในลำดับการโหลดของ DLL ซึ่งอาจเป็นผลจากการใช้ DLL ก่อนที่ระบบจะดำเนินการโค้ดเริ่มต้น ในทำนองเดียวกัน ฟังก์ชันจุดเข้าใช้งานไม่ควรเรียกใช้ฟังก์ชัน FreeLibrary (หรือฟังก์ชันที่เรียกฟังก์ชันดังกล่าว) เนื่องจากอาจทำให้ DLL กลายเป็นใช้งานหลังจากที่ระบบได้ดำเนินการโค้ดทางออกแล้ว

ตัวอย่างจากไมโครซอฟต์ คำแนะนำทีละขั้นตอน การสร้างและใช้งาน DLL (C++) Visual Studio 2013

การฝึกปฏิบัตินี้อธิบายวิธีการสร้างไดนามิกลิงก์ไลบรารี (DLL) เพื่อใช้กับแอปพลิเคชัน C++ การใช้ไลบรารีเป็นวิธีที่ดีในการนำโค้ดกลับมาใช้ใหม่ แทนที่จะนำขั้นตอนเดิมไปใช้ใหม่ในทุกโปรแกรม คุณสร้างมันขึ้นมาเพียงครั้งเดียวแล้วอ้างอิงจากแอพพลิเคชั่นอื่น ด้วยการวางโค้ดใน DLL คุณจะประหยัดพื้นที่ในแต่ละแอปพลิเคชันที่อ้างอิงโค้ด และคุณจะสามารถอัปเดต DLL ได้โดยไม่ต้องคอมไพล์แอปพลิเคชันทั้งหมดใหม่ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ DLL ดู DLL ใน Visual C++