Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A CodeQL egy hatékony statikus elemzési motor, amely segít a fejlesztőknek azonosítani a windowsos illesztőprogram forráskódjában található biztonsági réseket és kódsértéseket. Ez a cikk bemutatja, hogyan hozhat létre illesztőprogram-ellenőrző fájlt a Windows Hardverkompatibilitási program (WHCP) tanúsítványához a CodeQL-elemzés használatával.
Ebben a cikkben a következőt találja:
- Telepítse a megfelelő CodeQL-verziót.
- Telepítse a szükséges CodeQL-csomagokat és lekérdezési csomagokat.
- Futtassa a CodeQL-t egy adatbázis létrehozásához és a kód elemzéséhez.
- Illesztőprogram-ellenőrző fájl létrehozása.
Válassza ki az illesztőprogramnak megfelelő CodeQL-verziót
Note
A Visual Studio (VS) 17.8 kompatibilitása megszakadt az WHCP_21H2 és WHCP_22H2 ágakban használt CodeQL régebbi verzióival. A CodeQL CLI 2.15.4-es verziója érvényesítve van a WHCP 21H2 és WHCP 22H2 használatára, ha a Visual Studio 17.8 vagy újabb verzióját használják. A Visual Studio 17.7-es vagy korábbi verzióiban használja a 2.4.6-os vagy a 2.6.3-os verziót. A WHCP-programhoz használja a CodeQL CLI-verziót és a windowsos kiadást, amelyet a 2.4.6-os, a 2.6.3-os vagy a 2.15.4-es verzióhoz hitelesít. A főággal való általános használathoz használja a CodeQL CLI 2.15.4-es verzióját.
Válassza ki a forgatókönyv fülét:
Ezzel a mátrixszal meghatározhatja a letöltendő verziókat.
| Windows-kiadás | CodeQL parancssori verzió | A CodeQL-csomag microsoft/windows-drivers verziója | microsoft/cpp-queries CodeQL csomag verziója | codeql/cpp-queries verziószám | Használandó társított adattárág |
|---|---|---|---|---|---|
| Windows Server 2022 | 2.4.6 vagy 2.15.4 | 1.0.13 (2.15.4-es kód használata esetén) | N/A | 0.9.0 (Ha a 2.15.4-es codeql-t használja) | WHCP_21H2 |
| Windows 11 | 2.4.6 vagy 2.15.4 | 1.0.13 (2.15.4-es kód használata esetén) | N/A | 0.9.0 (Ha a 2.15.4-es codeql-t használja) | WHCP_21H2 |
| Windows 11, 22H2-es verzió | 2.6.3 vagy 2.15.4 | 1.0.13 (2.15.4-es kód használata esetén) | N/A | 0.9.0 (Ha a 2.15.4-es codeql-t használja) | WHCP_22H2 |
| Windows 11, 23H2-es verzió | 2.6.3 vagy 2.15.4 | 1.0.13 (2.15.4-es kód használata esetén) | N/A | 0.9.0 (Ha a 2.15.4-es codeql-t használja) | WHCP_22H2 |
| Windows 11, 24H2-es verzió | 2.15.4 | 1.1.0 | N/A | 0.9.0 | WHCP_24H2 |
| Windows Server 2025 | 2.20.1 | 1.6.0 | 0.0.4 | N/A | WHCP_25H2 |
| Windows 11, 25H2-es verzió | 2.20.1 | 1.6.0 | 0.0.4 | N/A | WHCP_25H2 |
Note
A CodeQL-csomag egy verziója nincs megadva a CodeQL CLI 2.4.6-os és 2.6.3-os verziójához, mert csak a CodeQL 2.7.0-s verziónál későbbi verziói támogatják a CodeQL-csomagokat.
A WHCP-vel való használatra ellenőrzött CodeQL-verziók
A legújabb verzióinformációkért, beleértve a legújabb fejlesztés tesztelését, tekintse meg a Windows illesztőprogram-fejlesztői kiegészítő eszközeit.
| CodeQL parancssori verzió |
|---|
| 2.21.4 |
| 2.21.2 |
| 2.20.1 |
| 2.15.4 |
A CodeQL letöltése és telepítése
Hozzon létre egy könyvtárat, amely tartalmazza a CodeQL-t. Ez a példa a
C:\codeql-home\-t használja.C:\> mkdir C:\codeql-homeAz előző táblázatokban kiválaszthatja, hogy a CodeQL CLI melyik verzióját használja a Microsoft illesztőprogram-lekérdezéseinek kívánt ágával összhangban. Ha a WHCP-program részeként végez elemzést, tekintse meg a Windows hardverkompatibilitási program használata táblát, egyébként használja a Fő ágat és a 2.15.4-et. Ha egy másik verziót használ, az adatbázis nem kompatibilis a kódtárakkal.
Lépjen az előző táblákhoz társított CodeQL CLI bináris fájlok kiadásához, és töltse le a zip-fájlt a projekt architektúrájának megfelelően. Például 64 bites Windows codeql-win64.zip.
Bontsa ki a Codeql CLI-könyvtárat az imént létrehozott könyvtárba, például: C:\codeql-home\codeql\.
Ellenőrizze, hogy a CodeQL megfelelően van-e telepítve a verzió ellenőrzésével:
C:\codeql-home\codeql>codeql --version CodeQL command-line toolchain release 2.15.4. Copyright (C) 2019-2023 GitHub, Inc. Unpacked in: C:\codeql-home\codeql Analysis results depend critically on separately distributed query and extractor modules. To list modules that are visible to the toolchain, use 'codeql resolve qlpacks' and 'codeql resolve languages'.
A CodeQL súgójának használata
C:\codeql-home\codeql\>codeql --help
Usage: codeql <command> <argument>...
Create and query CodeQL databases, or work with the QL language.
GitHub makes this program freely available for the analysis of open-source software and certain other uses, but it is
not itself free software. Type codeql --license to see the license terms.
--license Show the license terms for the CodeQL toolchain.
Common options:
-h, --help Show this help text.
-v, --verbose Incrementally increase the number of progress messages printed.
-q, --quiet Incrementally decrease the number of progress messages printed.
Some advanced options have been hidden; try --help -v for a fuller view.
Commands:
query Compile and execute QL code.
bqrs Get information from .bqrs files.
database Create, analyze and process CodeQL databases.
dataset [Plumbing] Work with raw QL datasets.
test Execute QL unit tests.
resolve [Deep plumbing] Helper commands to resolve disk locations etc.
execute [Deep plumbing] Low-level commands that need special JVM options.
version Show the version of the CodeQL toolchain.
generate Generate formatted QL documentation.
Ha segítségre van szüksége egy adott parancshoz, futtassa a codeql <parancsot> – súgó. Például:
codeql create --help
Ha segítségre van szüksége az alparancsokhoz, listázhatja őket hierarchikusan, például
codeql create language --help
A CodeQL-csomagok telepítése
Válassza ki a buildkörnyezet lapját:
Ezt az eljárást akkor használja, ha a Visual Studio 2022 17.8 vagy újabb verzióját használja WHCP_21H2 vagy WHCP_22H2 és a CodeQL CLI 2.15.4-es verziójával.
Note
Ha a CodeQL-teszteket a CodeQL egy korábbi verziójával futtatta, távolítsa el a régi CodeQL-almodult, ha még rendelkezik a klónozott adattár régi verziójával. Előfordulhat, hogy a CodeQL alapértelmezés szerint megpróbálja használni a lekérdezéseket az almodulban, ami a nem egyező verziók miatt hibákat okozhat.
A CodeQL-lekérdezéscsomagok letöltése
A CodeQL a CodeQL-csomagokat (CodeQL-csomagokat vagy lekérdezéscsomagokat) a 2.7.0-s verzióban vezette be, így nem szükséges klónozni a Windows-Driver-Developer-Supplemental-Tools adattárat a lekérdezések hitelesítéshez való használatához.
Note
Az 1. lépés kihagyható, mivel a --download lehetőség az elemzési folyamat futtatásakor később letölti a szükséges lekérdezéseket.
- Töltse le a microsoft/windows-drivers csomag megfelelő verzióját a Windows hardverkompatibilitási program használati táblázatából. Adja meg a
@<version>következő parancsot.
C:\codeql-home\> codeql pack download microsoft/windows-drivers@<version>
Ha például WHCP_24H2 használ, futtassa a következő parancsot az 1.1.0-s windows-drivers lekérdezési csomag letöltéséhez:
C:\codeql-home\> codeql pack download microsoft/windows-drivers@1.1.0
Ezzel a paranccsal letöltheti a CodeQL cpp-query lekérdezéscsomag 0.9.0-s verzióját.
C:\codeql-home\> codeql pack download microsoft/cpp-queries@0.9.0
A CodeQL telepíti a lekérdezéscsomagokat az alapértelmezett könyvtárba:
C:\Users\<current user>\.codeql\packages\microsoft\windows-drivers\<downloaded version>\
Important
Ne módosítsa a telepítési könyvtárat, és ne helyezze át a telepített lekérdezéscsomagot.
A Windows illesztőprogram-lekérdezési csomagjának letöltése
A Microsoft két lekérdezéscsomagot biztosít a végpontok közötti illesztőprogramok fejlesztői munkafolyamatának egyszerűsítéséhez. Az ajánlott.qls csomag az összes olyan lekérdezés szuperhalmaza, amelyet a Microsoft értékesnek tart az illesztőprogram-fejlesztők számára, a mustfix.qls csomag pedig a WHCP-minősítéshez szükségesnek ítélt lekérdezéseket tartalmazza. A mustfix.qls-eket futtatni kell, és át kell adni a statikus eszközök emblémájának teszteléséhez.
Másolja a két lekérdezéscsomagfájlt a helyi számítógépére https://github.com/microsoft/Windows-Driver-Developer-Supplemental-Tools/tree/main/src/windows-driver-suites .
- recommended.qls
- mustfix.qls
A lekérdezési csomagok tartalmáról további információt a CodeQL-lekérdezések és -csomagok című témakörben talál.
A CodeQL-adatbázis létrehozása
Ezek a példák feltételezik, hogy windowsos fejlesztői környezetet használnak, és a telepítés helye C:\codeql-home, de használhatja az Önnek megfelelő beállítást. Tekintse meg a CodeQL által támogatott nyelveket és keretrendszereket , amelyek listáját a fordítók támogatják.
Hozzon létre egy könyvtárat a CodeQL-hez az általa létrehozott adatbázisok elhelyezéséhez. Például: C:\codeql-home\databases
mkdir C:\codeql-home\databasesA CodeQL paranccsal hozzon létre adatbázist az alábbi paraméterekkel:
- Az első paraméter az adatbázis könyvtárára mutató hivatkozás. Például: C:\codeql-home\databases\MyDriverDatabase. (Ez a parancs meghiúsul, ha a könyvtár már létezik.)
-
--languagevagy-lmegadja a forráskód nyelvét vagy nyelvét. Ez lehet vesszővel tagolt lista, például [cpp, javascript]. -
--source-rootvagy-smegadja a forráskód elérési útját. -
--commandvagy-cmegadja a buildelési parancsot vagy a buildfájl elérési útját.
codeql database create <path to new database> --language=<cpp> --source-root=<driver parent directory> --command=<build command or path to build file>
Examples
Egyszeres meghajtó példa.
C:\codeql-home\codeql> codeql database create D:\DriverDatabase --language=cpp --source-root=D:\Drivers\SingleDriver --command="msbuild /t:rebuild D:\Drivers\SingleDriver\SingleDriver.sln"
Több vezérlő példa.
C:\codeql-home\codeql> codeql database create D:\SampleDriversDatabase --language=cpp --source-root=D:\AllMyDrivers\SampleDrivers --command=D:\AllMyDrivers\SampleDrivers\BuildAllSampleDrivers.cmd
A parancs használatával kapcsolatos további információkért vagy segítségért lásd: database createCodeQL-adatbázisok létrehozása vagy CodeQL-súgó.
Elemzés végrehajtása
Ezen a ponton az adatbázis létrehozása befejeződött, a következő lépés pedig az illesztőprogram forráskódjának tényleges elemzése.
A CodeQL paranccsal elemezheti az adatbázist a következő paraméterekkel:
- az első paraméter az adatbázis könyvtárára mutató hivatkozás. Például : C:\codeql-home\databases\MyDriverDatabase. (Megjegyzés: ez a parancs meghiúsul, ha a könyvtár nem létezik.)
-
--formata kimeneti fájl fájltípusa. A lehetőségek a következők: SARIF és CSV. (A WHCP-felhasználók a SARIF formátumot használják.) -
--outputa kimeneti fájl elérési útja, mindenképpen adja meg a formátumot a fájlnévben. (Ez a parancs meghiúsul, ha a könyvtár még nem létezik.) - a lekérdezéskijelölő paraméter az argumentumok szóközzel elválasztott listája, amely a következőket tartalmazhatja:
- egy lekérdezésfájl elérési útja
- egy lekérdezésfájlokat tartalmazó könyvtár elérési útja
- egy lekérdezéscsomagfájl elérési útja
- CodeQL-lekérdezéscsomag neve
codeql database analyze <path to database> <path to query suite .qls file> --format=sarifv2.1.0 --output=<outputname>.sarifExample:
codeql database analyze D:\DriverDatabase suites/windows\recommended.qls --format=sarifv2.1.0 --output=D:\DriverAnalysis1.sarifTovábbi információ vagy segítség a
database analyzeparancs használatához: Adatbázisok elemzése a CodeQL parancssori felülettel, CodeQL-csomag használata CodeQL-adatbázis elemzéséhez vagy CodeQL-súgó használata.
Eredmények megtekintése és értelmezése
Ebben a szakaszban a SARIF formátumra összpontosítunk, mivel ez szükséges a következő lépésekhez, bár szívesen használja a CSV formátumot, ha jobban megfelel az igényeinek.
A statikus elemzési eredmények felcserélésére szolgáló statikus elemzési formátum (SARIF) egy JSON-típusformátum, amely statikus elemzési eredmények megosztására szolgál. További információ az OASIS Static Analysis Results Interchange Format (SARIF) szabványáról, arról, hogy a CodeQL hogyan használja a SARIF-kimenetet és a séma json-t.
Az elemzési eredmények értelmezésére számos módszer létezik, például az objektumokon végzett manuális rendezés. Íme néhány, amit használunk:
A Microsoft Sarif Viewer (Web) olyan funkciókkal rendelkezik, amelyekkel a SARIF-fájlt áthúzhatja a megtekintőbe, majd szabály szerint kategorizálva jelenítheti meg az eredményeket. Ez egy nagyon gyors és egyszerű módja annak, hogy megtekintsük a szabálysértések számát, vagy hogy mely lekérdezések rendelkeznek szabálysértésekkel, de kevésbé könnyű megtalálni a forráskód adatait a sorszámon kívül. Vegye figyelembe, hogy a lap nem frissül, ha nincsenek szabálysértések.
A Visual Studióhoz készült Microsoft SARIF Viewer nagyszerűen jeleníti meg az eredményeket a Visual Studióban, hogy zökkenőmentesen áttérjen az eredményekről a forráskódra.
A Visual Studio Code SARIF-bővítménye megnyit egy előnézeti panelt, és megjeleníti a CodeQL által jelentett hibákat, figyelmeztetéseket és problémákat. A Sarif-fájl olvasható formátumban való megjelenítéséhez nyissa meg a fájlt a Visual Studio Code-ban, és válassza a Shift-Alt-F billentyűkombinációt.
A SARIF-fájl legfontosabb szakasza az Results objektumon belüli Run tulajdonság. Minden lekérdezés rendelkezik egy Találat tulajdonsággal, amely részletesen ismerteti az észlelt szabálysértéseket és azok előfordulásának helyét. Ha nem található szabálysértés, a tulajdonság értéke üres lesz.
A lekérdezések olyan állapotok szerint vannak besorolva, mint a hiba, a figyelmeztetés és a probléma. Ez a besorolás azonban eltér attól, hogy a Windows hardverkompatibilitási programja és a Static Tools Logo Test hogyan osztályozza az eredményeket. A Must-Fix csomagban található lekérdezések hibáival rendelkező illesztőprogramok nem fognak átmenni a Static Tools emblémateszten, és nem lesznek hitelesítve, függetlenül a nyers lekérdezésfájl lekérdezési besorolásától (például figyelmeztetés).
A SARIF konvertálása illesztőprogram-ellenőrzési naplóformátumra (DVL)
A Static Tools emblémateszt egy illesztőprogram-ellenőrzési naplót (DVL) elemez, amely az illesztőprogram forráskódján futtatott CodeQL statikus elemzés lefordított eredménye. A SARIF-fájlokat három módon konvertálhatja DVL formátumba: Visual Studio, MSBuild vagy parancssorból a dvl.exe eszközzel. A lépések végrehajtásához tekintse meg az illesztőprogram-ellenőrzési napló létrehozását.
A Static Tools logo HLK-tesztjének további útmutatásai és a DVL-fájl helyének helyével kapcsolatos útmutatás a Statikus eszközök embléma teszt futtatásában található.
Troubleshooting
Ha a WHCP-vel tanúsít, először győződjön meg arról, hogy a célzott Windows-kiadáshoz kapcsolódó HLK-verziót használja, a Windows illesztőprogram-fejlesztői kiegészítő eszközök adattárában lévő megfelelő ágat és a CodeQL CLI megfelelő verzióját. A HLK/Windows kiadás kompatibilitási mátrixát a Windows Hardware Lab Kit és a Windows Release/Windows Driver Developer Supplemental Tools adattárfiókja/CodeQL CLI-verziója esetén a WhCP tábla a CodeQL-verzió kiválasztása szakaszban találja.
Hibák és megoldások
Az adatbázis verzióeltéréseivel kapcsolatos problémák esetén az alábbi eszközök hasznosak lehetnek.
A codeql-verzió parancs használatával megjelenítheti a codeql exe verzióját.
C:\codeql-home\codeql\>codeql version
CodeQL command-line toolchain release 2.4.0.
Copyright (C) 2019-2020 GitHub, Inc.
Unpacked in: C:\codeql-home\codeql\
Analysis results depend critically on separately distributed query and
extractor modules. To list modules that are visible to the toolchain,
use 'codeql resolve qlpacks' and 'codeql resolve languages'.
Az adatbázis-frissítési parancs frissíti az adatbázist. Vegye figyelembe, hogy ez egy egyirányú frissítés, és nem fordítható vissza. További információ: adatbázis-frissítés.
Választható eljárások
Igény szerint letilthatja a CodeQL-eredményeket, vagy futtathatja a buildelési és elemzési eljárásokat a Visual Studióban a buildelés utáni eseményként.
A CodeQL-eredmények letiltása
Az illesztőprogramokhoz készült CodeQL támogatja az eredmények letiltását. Az elnyomások jelenleg kényelmi funkcióként szolgálnak, hogy segítsenek a fejlesztőknek a problémák osztályozásában és a zaj csökkentésében, nem pedig azért, hogy megkerüljék a Must-Fix ellenőrzéseket. Jelenleg nincs hatással az illesztőprogram-ellenőrzési napló létrehozására vagy a Statikus eszközök emblémájának tesztelésére. A letiltások használatához a DriverAlertSuppression.ql lekérdezést a többi futtatni kívánt lekérdezéssel vagy csomagokkal egyidejűleg kell futtatnia. Ez a lekérdezés alapértelmezés szerint engedélyezve van, amikor a githubs fő-/fejlesztési ágából futtatja a csomagokat.
A Kódelemzésből portolt ellenőrzések esetében a meglévő kódelemzési letiltások teljesülnek. További információ: C++ figyelmeztető pragma.
-
Known limitation:Egy #pragma(letiltás) és #pragma(elfedés) nem kombinálható ugyanabban a sorban ebben az időpontban.
A CodeQL-ben újdonságként használt ellenőrzéseknél tiltsa le őket két dolog egyikével:
Írjon megjegyzést
#pragma(suppress:the-rule-id-here)(idézőjelek nélkül) a szabálysértés fölötti sorra, ahogyan a Kódelemzés esetében is. Cserélje le a "the-rule-id-here" kifejezést a@idlekérdezés metaadatainak értékére, amely a fájl tetején látható.Írjon megjegyzést a fenti sorra, amely az "lgtm[the-rule-id-here]" szövegből áll (idézőjelek nélkül). Az illesztőprogram-riasztások letiltási lekérdezése helyett a szabványos C/C++ riasztáselnyomási lekérdezést kell futtatnia.
Ha a letiltás megjelenik és felismerhető, az eredményként kapott SARIF-fájl tartalmazni fogja az eredményeket letiltó adatokat, és a legtöbb eredménymegjelenítő alapértelmezés szerint nem jeleníti meg az eredményt.
Visual Studio – buildelés utáni esemény
Ha az illesztőprogramot a Visual Studióval készíti el, a CodeQL-lekérdezéseket konfigurálhatja a buildelés utáni eseményként való futtatásra.
Ebben a példában egy kis kötegfájl jön létre a célhelyen, és a buildelés utáni eseményként lesz meghívva. További információ a Visual Studio C++ buildeseményeiről: Buildesemények megadása.
Hozzon létre egy kis kötegfájlt, amely újra létrehozza a CodeQL-adatbázist, majd futtatja rajta a kívánt lekérdezéseket. Ebben a példában a kötegfájl neve el lesz nevezve
RunCodeQLRebuildQuery.bat. Módosítsa a példa kötegelt fájlban látható elérési utakat a címtár helyének megfelelően.ECHO ">>> Running CodeQL Security Rule V 1.0 <<<" ECHO ">>> Removing previously created rules database <<<" rmdir /s/q C:\codeql-home\databases\kmdf CALL C:\codeql-home\codeql\codeql\codeql.cmd database create -l=cpp -s="C:\codeql-home\drivers\kmdf" -c "msbuild /p:Configuration=Release /p:Platform=x64 C:\codeql-home\drivers\kmdf\kmdfecho.sln /t:rebuild /p:PostBuildEventUseInBuild=false " "C:\codeql-home\databases\kmdf" -j 0 CALL C:\codeql-home\codeql\codeql\codeql database analyze "C:\codeql-home\databases\kmdf" "<path to query suite .qls file>" --format=sarifv2.1.0 --output=C:\codeql-home\databases\kmdf.sarif -j 0 --rerun ECHO ">>> Loading SARIF Results in Visual Studio <<<" CALL devenv /Edit C:\codeql-home\databases\kmdf.sarif SET ERRORLEVEL = 0A kötegfájlban a devenv.exe/Szerkesztés beállítással nyithatja meg a SARIF-eredményfájlt a Visual Studio meglévő példányában. A SARIF-eredmények megtekintéséhez telepítse a Microsoft SARIF Viewer for Visual Studiót , és további információért tekintse meg az ott található utasításokat.
Az illesztőprogram-projektben keresse meg a projekt tulajdonságait. A Konfiguráció legördülő listában válassza ki azt a buildkonfigurációt, amelyet ellenőrizni szeretne a CodeQL-ben – a kiadást javasoljuk. A CodeQL-adatbázis létrehozása és a lekérdezések futtatása néhány percet vesz igénybe, ezért nem javasoljuk, hogy a CodeQL-t a projekt hibakeresési konfigurációján futtassa.
Válassza az Esemény összeállítása és a Build utáni esemény lehetőséget az illesztőprogram-projekt tulajdonságai között.
Adja meg a kötegfájl elérési útját és a buildelés utáni esemény leírását.
A kötegelt fájl eredményei a build kimenetének végén jelennek meg.
1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\MistypedFunctionArguments.ql. 1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\TooManyArguments.ql. 1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\TooFewArguments.ql. 1>Starting evaluation of codeql-cpp\Likely Bugs\Underspecified Functions\ImplicitFunctionDeclaration.ql. 1>[1/4 eval 4.4s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\TooManyArguments.bqrs. 1>[2/4 eval 4.4s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\TooFewArguments.bqrs. 1>[3/4 eval 4.5s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\ImplicitFunctionDeclaration.bqrs. 1>[4/4 eval 5.2s] Evaluation done; writing results to codeql-cpp\Likely Bugs\Underspecified Functions\MistypedFunctionArguments.bqrs. 1>Shutting down query evaluator. 1>Interpreting results. 1>">>> Loading SARIF Results in Visual Studio <<<"