Browse Source

first commit

main
gudae 2 months ago
commit
428099b20e
  1. BIN
      .vs/Housing.slnx/FileContentIndex/954979a5-62da-4f26-9d11-c5a91a363623.vsidx
  2. BIN
      .vs/Housing.slnx/FileContentIndex/b41067f8-87eb-4e55-a63c-be64322ec095.vsidx
  3. BIN
      .vs/Housing.slnx/FileContentIndex/bc759948-766a-4404-9c32-7764d1c2bd8e.vsidx
  4. BIN
      .vs/Housing.slnx/FileContentIndex/f6107c41-18b9-4848-a3e4-fb0d1130998d.vsidx
  5. BIN
      .vs/Housing.slnx/FileContentIndex/f83eb251-e51d-4065-b2b7-bb5686ba74a6.vsidx
  6. BIN
      .vs/Housing.slnx/v18/.suo
  7. BIN
      .vs/Housing.slnx/v18/.wsuo
  8. 37
      .vs/Housing.slnx/v18/DocumentLayout.json
  9. BIN
      .vs/Housing/CopilotIndices/18.3.511.5503/CodeChunks.db
  10. BIN
      .vs/Housing/CopilotIndices/18.3.511.5503/SemanticSymbols.db
  11. BIN
      .vs/Housing/DesignTimeBuild/.dtbcache.v2
  12. BIN
      .vs/Housing/FileContentIndex/1a868a9c-92ab-4c3b-b1fc-7da3654ec3e3.vsidx
  13. BIN
      .vs/Housing/FileContentIndex/2f5ca381-6d60-4191-8f9a-241d3356b237.vsidx
  14. BIN
      .vs/Housing/FileContentIndex/779353da-ca7b-4d23-a657-382b00ae1daa.vsidx
  15. BIN
      .vs/Housing/FileContentIndex/b65b73e0-c41b-4f5d-a425-7f85eeeee564.vsidx
  16. BIN
      .vs/Housing/FileContentIndex/cfd5f132-b59a-4cbb-8ced-370c8b8ada8a.vsidx
  17. BIN
      .vs/Housing/v18/.futdcache.v2
  18. BIN
      .vs/Housing/v18/.suo
  19. 103
      .vs/Housing/v18/DocumentLayout.backup.json
  20. 117
      .vs/Housing/v18/DocumentLayout.json
  21. BIN
      .vs/ProjectEvaluation/housing.metadata.v10.bin
  22. BIN
      .vs/ProjectEvaluation/housing.projects.v10.bin
  23. BIN
      .vs/ProjectEvaluation/housing.strings.v10.bin
  24. 3
      .vs/ProjectSettings.json
  25. 7
      .vs/VSWorkspaceState.json
  26. BIN
      .vs/slnx.sqlite
  27. 6
      App.xaml
  28. 16
      App.xaml.cs
  29. 8
      Database.ini
  30. 44
      Hardware.ini
  31. 25
      Housing.csproj
  32. 34
      Housing.sln
  33. 5
      InspectionSettings.ini
  34. 188
      Login/StartupLoginWindow.xaml
  35. 76
      Login/StartupLoginWindow.xaml.cs
  36. 248
      MainWindow.xaml
  37. 337
      MainWindow.xaml.cs
  38. 9
      Models/BoardMeasurementResult.cs
  39. 26
      Models/HousingAssemblyRecord.cs
  40. 17
      Models/InspectionJudgementSettings.cs
  41. 48
      Services/BoardHardwareSettings.cs
  42. 92
      Services/BoardTestService.cs
  43. 59
      Services/DatabaseSettings.cs
  44. 138
      Services/EquipmentMeasurementService.cs
  45. 84
      Services/EquipmentMeasurementSettings.cs
  46. 130
      Services/HousingAssemblyRepository.cs
  47. 7
      Services/IScpiClient.cs
  48. 45
      Services/IniFile.cs
  49. 58
      Services/InspectionSettingsStore.cs
  50. 193
      Services/SerialBoardClient.cs
  51. 132
      Services/SerialScpiClient.cs
  52. 92
      Services/TcpScpiClient.cs
  53. 214
      Services/VisaScpiClient.cs
  54. 23
      bin/Debug/net10.0-windows/Housing.deps.json
  55. BIN
      bin/Debug/net10.0-windows/Housing.dll
  56. BIN
      bin/Debug/net10.0-windows/Housing.exe
  57. BIN
      bin/Debug/net10.0-windows/Housing.pdb
  58. 19
      bin/Debug/net10.0-windows/Housing.runtimeconfig.json
  59. BIN
      bin/Debug/net9.0-windows/Azure.Core.dll
  60. BIN
      bin/Debug/net9.0-windows/Azure.Identity.dll
  61. 8
      bin/Debug/net9.0-windows/Database.ini
  62. 44
      bin/Debug/net9.0-windows/Hardware.ini
  63. 835
      bin/Debug/net9.0-windows/Housing.deps.json
  64. BIN
      bin/Debug/net9.0-windows/Housing.dll
  65. BIN
      bin/Debug/net9.0-windows/Housing.exe
  66. BIN
      bin/Debug/net9.0-windows/Housing.pdb
  67. 19
      bin/Debug/net9.0-windows/Housing.runtimeconfig.json
  68. 5
      bin/Debug/net9.0-windows/InspectionSettings.ini
  69. BIN
      bin/Debug/net9.0-windows/Microsoft.Bcl.AsyncInterfaces.dll
  70. BIN
      bin/Debug/net9.0-windows/Microsoft.Bcl.Cryptography.dll
  71. BIN
      bin/Debug/net9.0-windows/Microsoft.Data.SqlClient.dll
  72. BIN
      bin/Debug/net9.0-windows/Microsoft.Extensions.Caching.Abstractions.dll
  73. BIN
      bin/Debug/net9.0-windows/Microsoft.Extensions.Caching.Memory.dll
  74. BIN
      bin/Debug/net9.0-windows/Microsoft.Extensions.DependencyInjection.Abstractions.dll
  75. BIN
      bin/Debug/net9.0-windows/Microsoft.Extensions.Logging.Abstractions.dll
  76. BIN
      bin/Debug/net9.0-windows/Microsoft.Extensions.Options.dll
  77. BIN
      bin/Debug/net9.0-windows/Microsoft.Extensions.Primitives.dll
  78. BIN
      bin/Debug/net9.0-windows/Microsoft.Identity.Client.Extensions.Msal.dll
  79. BIN
      bin/Debug/net9.0-windows/Microsoft.Identity.Client.dll
  80. BIN
      bin/Debug/net9.0-windows/Microsoft.IdentityModel.Abstractions.dll
  81. BIN
      bin/Debug/net9.0-windows/Microsoft.IdentityModel.JsonWebTokens.dll
  82. BIN
      bin/Debug/net9.0-windows/Microsoft.IdentityModel.Logging.dll
  83. BIN
      bin/Debug/net9.0-windows/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll
  84. BIN
      bin/Debug/net9.0-windows/Microsoft.IdentityModel.Protocols.dll
  85. BIN
      bin/Debug/net9.0-windows/Microsoft.IdentityModel.Tokens.dll
  86. BIN
      bin/Debug/net9.0-windows/Microsoft.SqlServer.Server.dll
  87. BIN
      bin/Debug/net9.0-windows/System.ClientModel.dll
  88. BIN
      bin/Debug/net9.0-windows/System.IO.Ports.dll
  89. BIN
      bin/Debug/net9.0-windows/System.IdentityModel.Tokens.Jwt.dll
  90. BIN
      bin/Debug/net9.0-windows/System.Memory.Data.dll
  91. BIN
      bin/Debug/net9.0-windows/cs/Microsoft.Data.SqlClient.resources.dll
  92. BIN
      bin/Debug/net9.0-windows/de/Microsoft.Data.SqlClient.resources.dll
  93. BIN
      bin/Debug/net9.0-windows/es/Microsoft.Data.SqlClient.resources.dll
  94. BIN
      bin/Debug/net9.0-windows/fr/Microsoft.Data.SqlClient.resources.dll
  95. BIN
      bin/Debug/net9.0-windows/it/Microsoft.Data.SqlClient.resources.dll
  96. BIN
      bin/Debug/net9.0-windows/ja/Microsoft.Data.SqlClient.resources.dll
  97. BIN
      bin/Debug/net9.0-windows/ko/Microsoft.Data.SqlClient.resources.dll
  98. BIN
      bin/Debug/net9.0-windows/pl/Microsoft.Data.SqlClient.resources.dll
  99. BIN
      bin/Debug/net9.0-windows/pt-BR/Microsoft.Data.SqlClient.resources.dll
  100. BIN
      bin/Debug/net9.0-windows/ru/Microsoft.Data.SqlClient.resources.dll

BIN
.vs/Housing.slnx/FileContentIndex/954979a5-62da-4f26-9d11-c5a91a363623.vsidx

Binary file not shown.

BIN
.vs/Housing.slnx/FileContentIndex/b41067f8-87eb-4e55-a63c-be64322ec095.vsidx

Binary file not shown.

BIN
.vs/Housing.slnx/FileContentIndex/bc759948-766a-4404-9c32-7764d1c2bd8e.vsidx

Binary file not shown.

BIN
.vs/Housing.slnx/FileContentIndex/f6107c41-18b9-4848-a3e4-fb0d1130998d.vsidx

Binary file not shown.

BIN
.vs/Housing.slnx/FileContentIndex/f83eb251-e51d-4065-b2b7-bb5686ba74a6.vsidx

Binary file not shown.

BIN
.vs/Housing.slnx/v18/.suo

Binary file not shown.

BIN
.vs/Housing.slnx/v18/.wsuo

Binary file not shown.

37
.vs/Housing.slnx/v18/DocumentLayout.json

@ -0,0 +1,37 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\Users\\temp\\Desktop\\Housing\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:MainWindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 0,
"Children": [
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "MainWindow.xaml.cs",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml.cs",
"RelativeDocumentMoniker": "MainWindow.xaml.cs",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml.cs",
"RelativeToolTip": "MainWindow.xaml.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-05T02:47:48.556Z",
"EditorCaption": ""
}
]
}
]
}
]
}

BIN
.vs/Housing/CopilotIndices/18.3.511.5503/CodeChunks.db

Binary file not shown.

BIN
.vs/Housing/CopilotIndices/18.3.511.5503/SemanticSymbols.db

Binary file not shown.

BIN
.vs/Housing/DesignTimeBuild/.dtbcache.v2

Binary file not shown.

BIN
.vs/Housing/FileContentIndex/1a868a9c-92ab-4c3b-b1fc-7da3654ec3e3.vsidx

Binary file not shown.

BIN
.vs/Housing/FileContentIndex/2f5ca381-6d60-4191-8f9a-241d3356b237.vsidx

Binary file not shown.

BIN
.vs/Housing/FileContentIndex/779353da-ca7b-4d23-a657-382b00ae1daa.vsidx

Binary file not shown.

BIN
.vs/Housing/FileContentIndex/b65b73e0-c41b-4f5d-a425-7f85eeeee564.vsidx

Binary file not shown.

BIN
.vs/Housing/FileContentIndex/cfd5f132-b59a-4cbb-8ced-370c8b8ada8a.vsidx

Binary file not shown.

BIN
.vs/Housing/v18/.futdcache.v2

Binary file not shown.

BIN
.vs/Housing/v18/.suo

Binary file not shown.

103
.vs/Housing/v18/DocumentLayout.backup.json

@ -0,0 +1,103 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\Users\\temp\\Desktop\\Housing\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\login\\startuploginwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:login\\startuploginwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\database.ini||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:database.ini||{3B902123-F8A7-4915-9F01-361F908088D0}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\housing.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:housing.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 2,
"Children": [
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "Database.ini",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\Database.ini",
"RelativeDocumentMoniker": "Database.ini",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\Database.ini",
"RelativeToolTip": "Database.ini",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.002768|",
"WhenOpened": "2026-06-05T04:51:49.357Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "StartupLoginWindow.xaml",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\Login\\StartupLoginWindow.xaml",
"RelativeDocumentMoniker": "Login\\StartupLoginWindow.xaml",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\Login\\StartupLoginWindow.xaml",
"RelativeToolTip": "Login\\StartupLoginWindow.xaml",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
"WhenOpened": "2026-06-05T03:47:35.646Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "MainWindow.xaml",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml",
"RelativeDocumentMoniker": "MainWindow.xaml",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml",
"RelativeToolTip": "MainWindow.xaml",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
"WhenOpened": "2026-06-05T03:47:24.928Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "MainWindow.xaml.cs",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml.cs",
"RelativeDocumentMoniker": "MainWindow.xaml.cs",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml.cs",
"RelativeToolTip": "MainWindow.xaml.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwIAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-05T03:47:23.114Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 4,
"Title": "Housing",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\Housing.csproj",
"RelativeDocumentMoniker": "Housing.csproj",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\Housing.csproj",
"RelativeToolTip": "Housing.csproj",
"ViewState": "AgIAAAAAAAAAAAAAAADwvxkAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
"WhenOpened": "2026-06-05T03:47:09.586Z",
"EditorCaption": ""
}
]
}
]
}
]
}

117
.vs/Housing/v18/DocumentLayout.json

@ -0,0 +1,117 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\Users\\temp\\Desktop\\Housing\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\database.ini||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:database.ini||{3B902123-F8A7-4915-9F01-361F908088D0}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\hardware.ini||{3B902123-F8A7-4915-9F01-361F908088D0}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:hardware.ini||{3B902123-F8A7-4915-9F01-361F908088D0}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\login\\startuploginwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:login\\startuploginwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|c:\\users\\temp\\desktop\\housing\\housing.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|",
"RelativeMoniker": "D:0:0:{7364A567-F115-4ACE-9207-C6FDEEF0A394}|Housing.csproj|solutionrelative:housing.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 1,
"Children": [
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "Hardware.ini",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\Hardware.ini",
"RelativeDocumentMoniker": "Hardware.ini",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\Hardware.ini",
"RelativeToolTip": "Hardware.ini",
"ViewState": "AgIAAAMAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.002768|",
"WhenOpened": "2026-06-08T00:03:23.189Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "Database.ini",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\Database.ini",
"RelativeDocumentMoniker": "Database.ini",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\Database.ini",
"RelativeToolTip": "Database.ini",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.002768|",
"WhenOpened": "2026-06-05T04:51:49.357Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "StartupLoginWindow.xaml",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\Login\\StartupLoginWindow.xaml",
"RelativeDocumentMoniker": "Login\\StartupLoginWindow.xaml",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\Login\\StartupLoginWindow.xaml",
"RelativeToolTip": "Login\\StartupLoginWindow.xaml",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
"WhenOpened": "2026-06-05T03:47:35.646Z"
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "MainWindow.xaml",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml",
"RelativeDocumentMoniker": "MainWindow.xaml",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml",
"RelativeToolTip": "MainWindow.xaml",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|",
"WhenOpened": "2026-06-05T03:47:24.928Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 4,
"Title": "MainWindow.xaml.cs",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml.cs",
"RelativeDocumentMoniker": "MainWindow.xaml.cs",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\MainWindow.xaml.cs",
"RelativeToolTip": "MainWindow.xaml.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwIAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-05T03:47:23.114Z"
},
{
"$type": "Document",
"DocumentIndex": 5,
"Title": "Housing.csproj",
"DocumentMoniker": "C:\\Users\\temp\\Desktop\\Housing\\Housing.csproj",
"RelativeDocumentMoniker": "Housing.csproj",
"ToolTip": "C:\\Users\\temp\\Desktop\\Housing\\Housing.csproj",
"RelativeToolTip": "Housing.csproj",
"ViewState": "AgIAAAAAAAAAAAAAAADwvxkAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
"WhenOpened": "2026-06-05T03:47:09.586Z"
}
]
}
]
}
]
}

BIN
.vs/ProjectEvaluation/housing.metadata.v10.bin

Binary file not shown.

BIN
.vs/ProjectEvaluation/housing.projects.v10.bin

Binary file not shown.

BIN
.vs/ProjectEvaluation/housing.strings.v10.bin

Binary file not shown.

3
.vs/ProjectSettings.json

@ -0,0 +1,3 @@
{
"CurrentProjectSetting": null
}

7
.vs/VSWorkspaceState.json

@ -0,0 +1,7 @@
{
"ExpandedNodes": [
""
],
"SelectedNode": "\\MainWindow.xaml.cs",
"PreviewInSolutionExplorer": false
}

BIN
.vs/slnx.sqlite

Binary file not shown.

6
App.xaml

@ -0,0 +1,6 @@
<Application x:Class="Housing.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
</Application.Resources>
</Application>

16
App.xaml.cs

@ -0,0 +1,16 @@
using System.Windows;
namespace Housing;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ShutdownMode = ShutdownMode.OnMainWindowClose;
var mainWindow = new MainWindow();
MainWindow = mainWindow;
mainWindow.Show();
}
}

8
Database.ini

@ -0,0 +1,8 @@
[Database]
IP=127.0.0.1
Database=Housing
DbId=sa
DbPw=your_password
Encrypt=True
TrustServerCertificate=True
Timeout=5

44
Hardware.ini

@ -0,0 +1,44 @@
[Board]
PortName=Auto
BaudRate=115200
ReadTimeout=5000
ConnectCommand=x00c_001101:owt28006727ea97c7801
ReadIdCommand=x00c_001101:ow2800326003e
CalDefaultCommand=x00c_001001
EndToken=<end>
[Equipment]
; 목표: 장비 화면에 표시되는 현재 측정값을 읽습니다.
; V 출력: Keysight 34465A DMM 값
; A 출력: Keysight E36233A Power Supply CH1 Current 값
; USB 장비는 Keysight Connection Expert 또는 NI MAX에서 보이는 VISA 주소를 Resource에 넣으세요.
; 예: USB0::0x2A8D::0x1301::MY12345678::INSTR
Timeout=5000
SettleMilliseconds=300
; 34465A DMM
VoltageConnection=Visa
VoltageResource=
VoltageIdnMatch=34460,34461,34465,34470,3446,3447
VoltageSetupCommand=
VoltageReadCommand=MEAS:VOLT:DC?
; E36233A Power Supply
CurrentConnection=Visa
CurrentResource=
CurrentIdnMatch=E362
CurrentSetupCommand=
CurrentReadCommand=MEAS:CURR? CH1
; COM 포트로 잡히는 장비 예시:
; VoltageConnection=Serial
; VoltagePortName=Auto
; VoltageBaudRate=115200
; LAN 장비 예시:
; VoltageConnection=Tcp
; VoltageHost=192.168.0.10
; VoltagePort=5025
; E36233A 파워서플라이에서 CH1 전압까지 읽고 싶을 때 예시:
; VoltageReadCommand=MEAS:VOLT? CH1

25
Housing.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<RootNamespace>Housing</RootNamespace>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.3" />
<PackageReference Include="System.IO.Ports" Version="9.0.10" />
</ItemGroup>
<ItemGroup>
<None Update="Database.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Hardware.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="InspectionSettings.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

34
Housing.sln

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Housing", "Housing.csproj", "{7364A567-F115-4ACE-9207-C6FDEEF0A394}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Debug|x64.ActiveCfg = Debug|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Debug|x64.Build.0 = Debug|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Debug|x86.ActiveCfg = Debug|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Debug|x86.Build.0 = Debug|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Release|Any CPU.Build.0 = Release|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Release|x64.ActiveCfg = Release|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Release|x64.Build.0 = Release|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Release|x86.ActiveCfg = Release|Any CPU
{7364A567-F115-4ACE-9207-C6FDEEF0A394}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

5
InspectionSettings.ini

@ -0,0 +1,5 @@
[Judgement]
VMin=0.00
VMax=9.99
AMin=0.00
AMax=9.99

188
Login/StartupLoginWindow.xaml

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="utf-8"?>
<Window x:Class="Housing.Login.StartupLoginWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Housing Login"
Width="760"
Height="860"
MinWidth="560"
MinHeight="640"
d:DesignWidth="760"
d:DesignHeight="860"
WindowStartupLocation="CenterScreen"
Background="#141414"
UseLayoutRounding="True"
SnapsToDevicePixels="True">
<Window.Resources>
<Style x:Key="FieldLabelStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="InputStyle" TargetType="TextBox">
<Setter Property="Height" Value="52"/>
<Setter Property="MinWidth" Value="180"/>
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#DADADA"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="8,0"/>
</Style>
<Style x:Key="CommandButtonStyle" TargetType="Button">
<Setter Property="Height" Value="76"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#666666"/>
<Setter Property="BorderBrush" Value="#DADADA"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="FontSize" Value="30"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</Window.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled">
<Grid MinHeight="760" Margin="28">
<Border MaxWidth="680"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#4F4F4F"
BorderBrush="#BDBDBD"
BorderThickness="2"
Padding="28">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Text="Housing Assembly Login"
Foreground="White"
FontSize="36"
FontWeight="Bold"
HorizontalAlignment="Center"
TextWrapping="Wrap"/>
<Grid Grid.Row="2" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Maker" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="MakerTextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Grid Grid.Row="3" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Model" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="ModelTextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Grid Grid.Row="4" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Variant 1" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="Variant1TextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Grid Grid.Row="5" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Variant 2" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="Variant2TextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Grid Grid.Row="6" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="ID" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="OperatorTextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Grid Grid.Row="7" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="PW" Style="{StaticResource FieldLabelStyle}"/>
<PasswordBox x:Name="PasswordBox"
Grid.Column="1"
Height="52"
MinWidth="180"
Background="Black"
Foreground="White"
BorderBrush="#DADADA"
BorderThickness="2"
FontSize="24"
FontWeight="Bold"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Padding="8,0"/>
</Grid>
<Grid Grid.Row="8" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Line" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="LineNoTextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Grid Grid.Row="9" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Lot No" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="LotNoTextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Grid Grid.Row="10" Margin="0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Jig No" Style="{StaticResource FieldLabelStyle}"/>
<TextBox x:Name="JigNoTextBox" Grid.Column="1" Style="{StaticResource InputStyle}"/>
</Grid>
<Button Grid.Row="12"
Content="Log In"
Style="{StaticResource CommandButtonStyle}"
Click="LogInButton_Click"/>
</Grid>
</Border>
</Grid>
</ScrollViewer>
</Window>

76
Login/StartupLoginWindow.xaml.cs

@ -0,0 +1,76 @@
using System;
using System.Windows;
namespace Housing.Login;
public sealed class StartupLoginWindowResult
{
public string Maker { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
public string Variant1 { get; set; } = string.Empty;
public string Variant2 { get; set; } = string.Empty;
public string Operator { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string LineNo { get; set; } = string.Empty;
public string LotNo { get; set; } = string.Empty;
public string JigNo { get; set; } = string.Empty;
}
public partial class StartupLoginWindow : Window
{
private const string MasterId = "su";
private const string MasterPassword = "su";
public StartupLoginWindowResult Result { get; private set; } = new();
public StartupLoginWindow()
{
InitializeComponent();
OperatorTextBox.Focus();
}
private void LogInButton_Click(object sender, RoutedEventArgs e)
{
var loginId = OperatorTextBox.Text.Trim();
var password = PasswordBox.Password;
if (string.IsNullOrWhiteSpace(loginId))
{
MessageBox.Show(this, "ID를 입력하세요.", "Login", MessageBoxButton.OK, MessageBoxImage.Warning);
OperatorTextBox.Focus();
return;
}
if (string.IsNullOrWhiteSpace(password))
{
MessageBox.Show(this, "PW를 입력하세요.", "Login", MessageBoxButton.OK, MessageBoxImage.Warning);
PasswordBox.Focus();
return;
}
if (!string.Equals(loginId, MasterId, StringComparison.Ordinal) ||
!string.Equals(password, MasterPassword, StringComparison.Ordinal))
{
MessageBox.Show(this, "마스터 계정만 로그인할 수 있습니다.", "Login", MessageBoxButton.OK, MessageBoxImage.Error);
PasswordBox.Clear();
PasswordBox.Focus();
return;
}
Result = new StartupLoginWindowResult
{
Maker = MakerTextBox.Text.Trim(),
Model = ModelTextBox.Text.Trim(),
Variant1 = Variant1TextBox.Text.Trim(),
Variant2 = Variant2TextBox.Text.Trim(),
Operator = loginId,
Password = password,
LineNo = LineNoTextBox.Text.Trim(),
LotNo = LotNoTextBox.Text.Trim(),
JigNo = JigNoTextBox.Text.Trim()
};
DialogResult = true;
Close();
}
}

248
MainWindow.xaml

@ -0,0 +1,248 @@
<?xml version="1.0" encoding="utf-8"?>
<Window x:Class="Housing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Housing Assembly"
Width="1200"
Height="800"
MinWidth="840"
MinHeight="560"
WindowStartupLocation="CenterScreen"
WindowState="Maximized"
UseLayoutRounding="True"
SnapsToDevicePixels="True">
<Window.Resources>
<Style x:Key="LabelStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="#303030"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style x:Key="InputBoxStyle" TargetType="TextBox">
<Setter Property="Height" Value="60"/>
<Setter Property="MinWidth" Value="160"/>
<Setter Property="Background" Value="#FFFDF4"/>
<Setter Property="Foreground" Value="#111111"/>
<Setter Property="BorderBrush" Value="#B8B8B8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="10,0"/>
</Style>
<Style x:Key="OutputBoxStyle" TargetType="TextBox">
<Setter Property="MinHeight" Value="220"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#111111"/>
<Setter Property="BorderBrush" Value="#B8B8B8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontSize" Value="40"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="IsReadOnly" Value="True"/>
</Style>
<Style x:Key="RangeBoxStyle" TargetType="TextBox">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Background" Value="#FFFDF4"/>
<Setter Property="Foreground" Value="#111111"/>
<Setter Property="BorderBrush" Value="#B8B8B8"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="6,0,0,10"/>
</Style>
<Style x:Key="LogoutButtonStyle" TargetType="Button">
<Setter Property="Height" Value="34"/>
<Setter Property="MinWidth" Value="92"/>
<Setter Property="Padding" Value="12,0"/>
<Setter Property="Background" Value="#6A2B2B"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#6A2B2B"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</Window.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
Background="#F4F4F4">
<Grid MinHeight="620" Margin="28">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="22"/>
<RowDefinition Height="*"/>
<RowDefinition Height="22"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Housing Assembly 검사 화면"
Foreground="#111111"
FontSize="30"
FontWeight="Bold"
VerticalAlignment="Center"
TextWrapping="Wrap"/>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock Text="Login ID"
Foreground="#404040"
FontSize="18"
FontWeight="SemiBold"
Margin="0,0,10,0"
VerticalAlignment="Center"/>
<TextBlock x:Name="OperatorTextBlock"
Text="-"
Foreground="#111111"
FontSize="18"
FontWeight="Bold"
Margin="0,0,14,0"
VerticalAlignment="Center"/>
<Button x:Name="LogoutButton"
Content="로그아웃"
Style="{StaticResource LogoutButtonStyle}"
Visibility="Collapsed"
Click="LogoutButton_Click"/>
</StackPanel>
</Grid>
<Border Grid.Row="2"
Background="White"
BorderBrush="#D0D0D0"
BorderThickness="1"
Padding="22">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="22"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="PCB_Barcode 입력" Style="{StaticResource LabelStyle}"/>
<TextBox x:Name="BarcodeTextBox"
Grid.Row="1"
Style="{StaticResource InputBoxStyle}"
KeyDown="BarcodeTextBox_KeyDown"
TextChanged="BarcodeTextBox_TextChanged"/>
</Grid>
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="IC_SN 출력" Style="{StaticResource LabelStyle}"/>
<TextBox x:Name="IcSnOutputTextBox"
Grid.Row="1"
Style="{StaticResource InputBoxStyle}"
Background="White"
IsReadOnly="True"/>
</Grid>
</Grid>
</Border>
<Border Grid.Row="4"
Background="White"
BorderBrush="#D0D0D0"
BorderThickness="1"
Padding="22">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="22"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="22"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel LastChildFill="False">
<TextBlock Text="PT_Vol_1 / V 출력" Style="{StaticResource LabelStyle}"/>
<TextBox x:Name="VMinTextBox" Style="{StaticResource RangeBoxStyle}"/>
<TextBlock Text="~"
FontSize="18"
FontWeight="Bold"
Margin="6,0,0,10"
VerticalAlignment="Center"/>
<TextBox x:Name="VMaxTextBox" Style="{StaticResource RangeBoxStyle}"/>
</DockPanel>
<TextBox x:Name="VOutputTextBox"
Grid.Row="1"
Text="0.00"
Style="{StaticResource OutputBoxStyle}"/>
</Grid>
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel LastChildFill="False">
<TextBlock Text="PT_Current_1 / A 출력" Style="{StaticResource LabelStyle}"/>
<TextBox x:Name="AMinTextBox" Style="{StaticResource RangeBoxStyle}"/>
<TextBlock Text="~"
FontSize="18"
FontWeight="Bold"
Margin="6,0,0,10"
VerticalAlignment="Center"/>
<TextBox x:Name="AMaxTextBox" Style="{StaticResource RangeBoxStyle}"/>
</DockPanel>
<TextBox x:Name="AOutputTextBox"
Grid.Row="1"
Text="0.00"
Style="{StaticResource OutputBoxStyle}"/>
</Grid>
<Grid Grid.Column="4">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="Result / 결과 출력" Style="{StaticResource LabelStyle}"/>
<TextBox x:Name="ResultOutputTextBox"
Grid.Row="1"
Style="{StaticResource OutputBoxStyle}"
FontSize="22"
FontWeight="SemiBold"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Top"
TextWrapping="Wrap"
AcceptsReturn="True"
VerticalScrollBarVisibility="Auto"/>
</Grid>
</Grid>
</Border>
<Grid Grid.Row="6"/>
</Grid>
</ScrollViewer>
</Window>

337
MainWindow.xaml.cs

@ -0,0 +1,337 @@
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using Housing.Login;
using Housing.Models;
using Housing.Services;
namespace Housing;
public partial class MainWindow : Window
{
private const string BarcodeRequiredMessage = "PCB_Barcode를 입력하고 Enter를 눌러주세요.";
private const string BoardReadyMessage = "Enter를 누르면 보드 연결 테스트를 시작합니다.";
private const string DefaultOutputValue = "0.00";
private StartupLoginWindowResult _loginResult = new();
private InspectionJudgementSettings _inspectionSettings;
private bool _isStartupLoginShown;
private bool _isBoardTestRunning;
public MainWindow()
{
_inspectionSettings = InspectionSettingsStore.Load(GetInspectionSettingsIniPath());
InitializeComponent();
ApplyInspectionSettingsToTextBoxes();
ApplyLoginResult();
ResetScreen();
}
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (_isStartupLoginShown)
{
return;
}
_isStartupLoginShown = true;
if (!ShowLoginPopup())
{
Close();
}
}
private void BarcodeTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (string.IsNullOrWhiteSpace(BarcodeTextBox.Text))
{
IcSnOutputTextBox.Clear();
ResultOutputTextBox.Text = BarcodeRequiredMessage;
return;
}
ResultOutputTextBox.Text = BoardReadyMessage;
}
private async void BarcodeTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Enter && e.Key != Key.Return)
{
return;
}
e.Handled = true;
await RunBoardSequenceAsync();
}
public async Task OnEquipmentStartButtonPressedAsync()
{
await RunBoardSequenceAsync();
}
private async Task RunBoardSequenceAsync()
{
if (_isBoardTestRunning)
{
return;
}
if (string.IsNullOrWhiteSpace(BarcodeTextBox.Text))
{
ResultOutputTextBox.Text = BarcodeRequiredMessage;
FocusBarcodeInput();
return;
}
if (!TryApplyInspectionSettingsFromTextBoxes())
{
return;
}
try
{
_isBoardTestRunning = true;
SetInputEnabled(false);
ResultOutputTextBox.Text =
"보드 테스트 시작\r\n" +
"1. 시료 연결 확인\r\n" +
"2. IC_SN 읽기\r\n" +
"3. CAL DEFAULT 조건 설정\r\n" +
"4. 계측 장비에서 V/A 읽기";
var boardSettings = BoardHardwareSettings.Load(GetHardwareIniPath());
var equipmentSettings = EquipmentMeasurementSettings.Load(GetHardwareIniPath());
var service = new BoardTestService(boardSettings, equipmentSettings);
var measurement = await service.RunAsync();
IcSnOutputTextBox.Text = measurement.IcSn;
VOutputTextBox.Text = FormatDecimal(measurement.Voltage);
AOutputTextBox.Text = FormatDecimal(measurement.Current);
var resultCode = _inspectionSettings.IsPass(measurement.Voltage, measurement.Current) ? "OK" : "NG";
ResultOutputTextBox.Text = $"{resultCode}\r\n{measurement.RawLog}";
await SaveCurrentResultAsync(resultCode);
}
catch (Exception ex)
{
ResultOutputTextBox.Text = $"보드 테스트 실패: {ex.Message}";
}
finally
{
_isBoardTestRunning = false;
SetInputEnabled(true);
FocusBarcodeInput();
}
}
private void LogoutButton_Click(object sender, RoutedEventArgs e)
{
ResetScreen();
_loginResult = new StartupLoginWindowResult();
OperatorTextBlock.Text = "-";
LogoutButton.Visibility = Visibility.Collapsed;
if (!ShowLoginPopup())
{
Close();
}
}
private bool ShowLoginPopup()
{
var loginWindow = new StartupLoginWindow
{
Owner = this
};
if (loginWindow.ShowDialog() != true)
{
return false;
}
_loginResult = loginWindow.Result;
ApplyLoginResult();
ResetScreen();
return true;
}
private void ApplyLoginResult()
{
OperatorTextBlock.Text = string.IsNullOrWhiteSpace(_loginResult.Operator) ? "-" : _loginResult.Operator;
LogoutButton.Visibility = string.IsNullOrWhiteSpace(_loginResult.Operator)
? Visibility.Collapsed
: Visibility.Visible;
}
private void ResetScreen()
{
BarcodeTextBox.Clear();
IcSnOutputTextBox.Clear();
VOutputTextBox.Text = DefaultOutputValue;
AOutputTextBox.Text = DefaultOutputValue;
ResultOutputTextBox.Text = BarcodeRequiredMessage;
FocusBarcodeInput();
}
private void SetInputEnabled(bool isEnabled)
{
BarcodeTextBox.IsEnabled = isEnabled;
VMinTextBox.IsEnabled = isEnabled;
VMaxTextBox.IsEnabled = isEnabled;
AMinTextBox.IsEnabled = isEnabled;
AMaxTextBox.IsEnabled = isEnabled;
LogoutButton.IsEnabled = isEnabled;
}
private void FocusBarcodeInput()
{
Dispatcher.BeginInvoke(new Action(() =>
{
BarcodeTextBox.Focus();
Keyboard.Focus(BarcodeTextBox);
BarcodeTextBox.SelectAll();
}), DispatcherPriority.Input);
}
private async Task SaveCurrentResultAsync(string resultCode)
{
try
{
var repository = new HousingAssemblyRepository(DatabaseSettings.Load(GetDatabaseIniPath()));
var record = CreateCurrentRecord(resultCode);
await repository.InsertAsync(record);
ResultOutputTextBox.Text += "\r\nDB 저장 완료";
}
catch (Exception ex)
{
ResultOutputTextBox.Text += $"\r\nDB 저장 실패: {ex.Message}";
}
}
private HousingAssemblyRecord CreateCurrentRecord(string resultCode)
{
var barcode = BarcodeTextBox.Text.Trim();
var icSn = IcSnOutputTextBox.Text.Trim();
if (string.IsNullOrWhiteSpace(icSn))
{
icSn = barcode;
IcSnOutputTextBox.Text = icSn;
}
return new HousingAssemblyRecord
{
IcSn = icSn,
PcbBarcode = barcode,
Maker = _loginResult.Maker,
Model = _loginResult.Model,
Variant1 = _loginResult.Variant1,
Variant2 = _loginResult.Variant2,
Operator = _loginResult.Operator,
Password = _loginResult.Password,
ProductionDate = DateTime.Now,
Line = _loginResult.LineNo,
LotNo = _loginResult.LotNo,
JigNo = _loginResult.JigNo,
PtVol1 = ParseDecimal(VOutputTextBox.Text),
PtCurrent1 = ParseDecimal(AOutputTextBox.Text),
Result = resultCode
};
}
private void ApplyInspectionSettingsToTextBoxes()
{
VMinTextBox.Text = FormatDecimal(_inspectionSettings.VMin);
VMaxTextBox.Text = FormatDecimal(_inspectionSettings.VMax);
AMinTextBox.Text = FormatDecimal(_inspectionSettings.AMin);
AMaxTextBox.Text = FormatDecimal(_inspectionSettings.AMax);
}
private bool TryApplyInspectionSettingsFromTextBoxes()
{
if (!TryReadRangeValue(VMinTextBox, "V 최소값", out var vMin) ||
!TryReadRangeValue(VMaxTextBox, "V 최대값", out var vMax) ||
!TryReadRangeValue(AMinTextBox, "A 최소값", out var aMin) ||
!TryReadRangeValue(AMaxTextBox, "A 최대값", out var aMax))
{
return false;
}
if (vMin > vMax)
{
MessageBox.Show(this, "V 최소값은 최대값보다 클 수 없습니다.", "판정 범위", MessageBoxButton.OK, MessageBoxImage.Warning);
VMinTextBox.Focus();
return false;
}
if (aMin > aMax)
{
MessageBox.Show(this, "A 최소값은 최대값보다 클 수 없습니다.", "판정 범위", MessageBoxButton.OK, MessageBoxImage.Warning);
AMinTextBox.Focus();
return false;
}
_inspectionSettings = new InspectionJudgementSettings
{
VMin = vMin,
VMax = vMax,
AMin = aMin,
AMax = aMax
};
InspectionSettingsStore.Save(GetInspectionSettingsIniPath(), _inspectionSettings);
return true;
}
private bool TryReadRangeValue(TextBox textBox, string fieldName, out decimal value)
{
if (decimal.TryParse(textBox.Text, NumberStyles.Number, CultureInfo.InvariantCulture, out value))
{
return true;
}
if (decimal.TryParse(textBox.Text, out value))
{
return true;
}
MessageBox.Show(this, $"{fieldName}은 숫자로 입력하세요.", "판정 범위", MessageBoxButton.OK, MessageBoxImage.Warning);
textBox.Focus();
return false;
}
private static decimal ParseDecimal(string value)
{
return decimal.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out var result)
? result
: 0m;
}
private static string FormatDecimal(decimal value)
{
return value.ToString("0.00", CultureInfo.InvariantCulture);
}
private static string GetDatabaseIniPath()
{
return Path.Combine(AppContext.BaseDirectory, "Database.ini");
}
private static string GetHardwareIniPath()
{
return Path.Combine(AppContext.BaseDirectory, "Hardware.ini");
}
private static string GetInspectionSettingsIniPath()
{
return Path.Combine(AppContext.BaseDirectory, "InspectionSettings.ini");
}
}

9
Models/BoardMeasurementResult.cs

@ -0,0 +1,9 @@
namespace Housing.Models;
public sealed class BoardMeasurementResult
{
public string IcSn { get; set; } = string.Empty;
public decimal Voltage { get; set; }
public decimal Current { get; set; }
public string RawLog { get; set; } = string.Empty;
}

26
Models/HousingAssemblyRecord.cs

@ -0,0 +1,26 @@
using System;
namespace Housing.Models;
public sealed class HousingAssemblyRecord
{
public string IcSn { get; set; } = string.Empty;
public string PcbBarcode { get; set; } = string.Empty;
public string Maker { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
public string Variant1 { get; set; } = string.Empty;
public string Variant2 { get; set; } = string.Empty;
public string Operator { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public DateTime ProductionDate { get; set; } = DateTime.Now;
public string Line { get; set; } = string.Empty;
public string LotNo { get; set; } = string.Empty;
public string JigNo { get; set; } = string.Empty;
public decimal PtVol1 { get; set; }
public decimal PtCurrent1 { get; set; }
public string Result { get; set; } = string.Empty;
public string Spare1 { get; set; } = string.Empty;
public string Spare2 { get; set; } = string.Empty;
public string Spare3 { get; set; } = string.Empty;
public string Spare4 { get; set; } = string.Empty;
}

17
Models/InspectionJudgementSettings.cs

@ -0,0 +1,17 @@
namespace Housing.Models;
public sealed class InspectionJudgementSettings
{
public decimal VMin { get; set; } = 0.00m;
public decimal VMax { get; set; } = 9.99m;
public decimal AMin { get; set; } = 0.00m;
public decimal AMax { get; set; } = 9.99m;
public bool IsPass(decimal voltage, decimal current)
{
return voltage >= VMin &&
voltage <= VMax &&
current >= AMin &&
current <= AMax;
}
}

48
Services/BoardHardwareSettings.cs

@ -0,0 +1,48 @@
using System.IO;
namespace Housing.Services;
public sealed class BoardHardwareSettings
{
public string PortName { get; set; } = "Auto";
public int BaudRate { get; set; } = 115200;
public int ReadTimeout { get; set; } = 5000;
public string ConnectCommand { get; set; } = "x00c_001101:owt28006727ea97c7801";
public string ReadIdCommand { get; set; } = "x00c_001101:ow2800326003e";
public string CalDefaultCommand { get; set; } = "x00c_001001";
public string EndToken { get; set; } = "<end>";
public static BoardHardwareSettings Load(string filePath)
{
if (!File.Exists(filePath))
{
throw new FileNotFoundException("Hardware.ini 파일을 찾을 수 없습니다.", filePath);
}
var values = IniFile.LoadSection(filePath, "Board");
return new BoardHardwareSettings
{
PortName = GetString(values, "PortName", "Auto"),
BaudRate = GetInt(values, "BaudRate", 115200),
ReadTimeout = GetInt(values, "ReadTimeout", 5000),
ConnectCommand = GetString(values, "ConnectCommand", "x00c_001101:owt28006727ea97c7801"),
ReadIdCommand = GetString(values, "ReadIdCommand", "x00c_001101:ow2800326003e"),
CalDefaultCommand = GetString(values, "CalDefaultCommand", "x00c_001001"),
EndToken = GetString(values, "EndToken", "<end>")
};
}
private static string GetString(Dictionary<string, string> values, string key, string defaultValue)
{
return values.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value)
? value.Trim()
: defaultValue;
}
private static int GetInt(Dictionary<string, string> values, string key, int defaultValue)
{
return values.TryGetValue(key, out var value) && int.TryParse(value, out var result)
? result
: defaultValue;
}
}

92
Services/BoardTestService.cs

@ -0,0 +1,92 @@
using System.Text;
using System.Text.RegularExpressions;
using Housing.Models;
namespace Housing.Services;
public sealed class BoardTestService
{
private readonly BoardHardwareSettings _boardSettings;
private readonly EquipmentMeasurementSettings _equipmentSettings;
public BoardTestService(BoardHardwareSettings boardSettings, EquipmentMeasurementSettings equipmentSettings)
{
_boardSettings = boardSettings;
_equipmentSettings = equipmentSettings;
}
public async Task<BoardMeasurementResult> RunAsync()
{
using var boardClient = new SerialBoardClient(_boardSettings);
var log = new StringBuilder();
log.AppendLine($"> BOARD PORT: {boardClient.PortName} @ {_boardSettings.BaudRate}");
var connectResponse = await SendAndLogAsync(boardClient, "CONNECT", _boardSettings.ConnectCommand, _boardSettings.ReadTimeout, true, log);
if (!ContainsSuccess(connectResponse))
{
throw new InvalidOperationException("시료 연결 확인 실패");
}
var idResponse = await SendAndLogAsync(boardClient, "READ_ID", _boardSettings.ReadIdCommand, _boardSettings.ReadTimeout, true, log);
var icSn = ExtractFirstHexLine(idResponse);
if (string.IsNullOrWhiteSpace(icSn))
{
throw new InvalidOperationException("IC_SN 읽기 실패");
}
await SendAndLogAsync(boardClient, "CAL_DEFAULT", _boardSettings.CalDefaultCommand, _boardSettings.ReadTimeout, false, log);
var equipmentService = new EquipmentMeasurementService(_equipmentSettings);
var equipmentResult = await equipmentService.ReadAsync();
log.Append(equipmentResult.RawLog);
return new BoardMeasurementResult
{
IcSn = icSn,
Voltage = equipmentResult.Voltage,
Current = equipmentResult.Current,
RawLog = log.ToString()
};
}
private static async Task<string> SendAndLogAsync(
SerialBoardClient client,
string label,
string command,
int timeoutMilliseconds,
bool waitForEndToken,
StringBuilder log)
{
log.AppendLine($"> BOARD {label}: {command}");
var response = await client.SendCommandAsync(command, timeoutMilliseconds, waitForEndToken);
log.Append(response);
return response;
}
private static bool ContainsSuccess(string response)
{
return response
.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
.Any(line => string.Equals(line.Trim(), "Success", StringComparison.OrdinalIgnoreCase));
}
private static string ExtractFirstHexLine(string response)
{
foreach (var rawLine in response.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries))
{
var line = rawLine.Trim();
if (line.Equals("<end>", StringComparison.OrdinalIgnoreCase) ||
line.Equals("Fail", StringComparison.OrdinalIgnoreCase))
{
continue;
}
if (Regex.IsMatch(line, "^[0-9A-Fa-f]{8,32}$"))
{
return line.ToUpperInvariant();
}
}
return string.Empty;
}
}

59
Services/DatabaseSettings.cs

@ -0,0 +1,59 @@
using System.IO;
namespace Housing.Services;
public sealed class DatabaseSettings
{
public string Ip { get; set; } = string.Empty;
public string Database { get; set; } = string.Empty;
public string DbId { get; set; } = string.Empty;
public string DbPw { get; set; } = string.Empty;
public bool Encrypt { get; set; } = true;
public bool TrustServerCertificate { get; set; } = true;
public int Timeout { get; set; } = 5;
public static DatabaseSettings Load(string filePath)
{
if (!File.Exists(filePath))
{
throw new FileNotFoundException("Database.ini 파일을 찾을 수 없습니다.", filePath);
}
var values = IniFile.LoadSection(filePath, "Database");
return new DatabaseSettings
{
Ip = GetValue(values, "IP", "Server"),
Database = GetValue(values, "Database", "DB"),
DbId = GetValue(values, "DbId", "UserId", "ID"),
DbPw = GetValue(values, "DbPw", "Password", "PW"),
Encrypt = GetBool(values, true, "Encrypt"),
TrustServerCertificate = GetBool(values, true, "TrustServerCertificate"),
Timeout = GetInt(values, 5, "Timeout")
};
}
private static string GetValue(Dictionary<string, string> values, params string[] keys)
{
foreach (var key in keys)
{
if (values.TryGetValue(key, out var value))
{
return value.Trim();
}
}
return string.Empty;
}
private static bool GetBool(Dictionary<string, string> values, bool defaultValue, params string[] keys)
{
var value = GetValue(values, keys);
return string.IsNullOrWhiteSpace(value) ? defaultValue : bool.Parse(value);
}
private static int GetInt(Dictionary<string, string> values, int defaultValue, params string[] keys)
{
var value = GetValue(values, keys);
return string.IsNullOrWhiteSpace(value) ? defaultValue : int.Parse(value);
}
}

138
Services/EquipmentMeasurementService.cs

@ -0,0 +1,138 @@
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using Housing.Models;
namespace Housing.Services;
public sealed class EquipmentMeasurementService
{
private readonly EquipmentMeasurementSettings _settings;
public EquipmentMeasurementService(EquipmentMeasurementSettings settings)
{
_settings = settings;
}
public async Task<BoardMeasurementResult> ReadAsync()
{
var log = new StringBuilder();
if (_settings.SettleMilliseconds > 0)
{
await Task.Delay(_settings.SettleMilliseconds);
}
var voltage = await ReadChannelAsync("VOLTAGE", _settings.Voltage, log);
var current = await ReadChannelAsync("CURRENT", _settings.Current, log);
return new BoardMeasurementResult
{
Voltage = voltage,
Current = current,
RawLog = log.ToString()
};
}
private async Task<decimal> ReadChannelAsync(string label, ScpiChannelSettings channel, StringBuilder log)
{
if (string.IsNullOrWhiteSpace(channel.ReadCommand))
{
throw new InvalidOperationException($"Hardware.ini [Equipment] {label} ReadCommand 값을 확인하세요.");
}
using var client = await CreateClientAsync(label, channel);
log.AppendLine($"> {label} CONNECT: {DescribeClient(client, channel)}");
if (!string.IsNullOrWhiteSpace(channel.SetupCommand))
{
log.AppendLine($"> {label} SETUP: {channel.SetupCommand}");
await client.SendAsync(channel.SetupCommand);
}
log.AppendLine($"> {label} READ: {channel.ReadCommand}");
var response = await client.QueryAsync(channel.ReadCommand);
log.AppendLine(response);
return ExtractFirstDecimal(response, label);
}
private Task<IScpiClient> CreateClientAsync(string label, ScpiChannelSettings channel)
{
var connection = GetConnectionType(channel);
return connection switch
{
"TCP" or "LAN" => CreateTcpClientAsync(label, channel),
"SERIAL" or "COM" => Task.FromResult<IScpiClient>(new SerialScpiClient(channel.PortName, channel.BaudRate, _settings.Timeout, channel.GetIdnMatches())),
"VISA" or "USB" => CreateVisaClientAsync(channel),
_ => throw new InvalidOperationException($"{label} 장비 연결 방식은 Visa, Serial, Tcp 중 하나로 설정하세요.")
};
}
private static string GetConnectionType(ScpiChannelSettings channel)
{
if (!string.IsNullOrWhiteSpace(channel.Connection))
{
return channel.Connection.Trim().ToUpperInvariant();
}
if (!string.IsNullOrWhiteSpace(channel.ResourceName))
{
return "VISA";
}
if (!string.IsNullOrWhiteSpace(channel.IdnMatch))
{
return "VISA";
}
if (!string.IsNullOrWhiteSpace(channel.PortName))
{
return "SERIAL";
}
if (!string.IsNullOrWhiteSpace(channel.Host))
{
return "TCP";
}
return string.Empty;
}
private async Task<IScpiClient> CreateTcpClientAsync(string label, ScpiChannelSettings channel)
{
if (string.IsNullOrWhiteSpace(channel.Host))
{
throw new InvalidOperationException($"Hardware.ini [Equipment] {label} Host 값을 확인하세요.");
}
return await TcpScpiClient.ConnectAsync(channel.Host, channel.Port, _settings.Timeout);
}
private async Task<IScpiClient> CreateVisaClientAsync(ScpiChannelSettings channel)
{
return await VisaScpiClient.OpenMatchingAsync(channel.ResourceName, channel.GetIdnMatches(), _settings.Timeout);
}
private static string DescribeClient(IScpiClient client, ScpiChannelSettings channel)
{
return client switch
{
SerialScpiClient serial => $"Serial {serial.PortName} @ {channel.BaudRate}",
VisaScpiClient visa => $"VISA {visa.ResourceName}",
TcpScpiClient => $"TCP {channel.Host}:{channel.Port}",
_ => channel.Connection
};
}
private static decimal ExtractFirstDecimal(string response, string label)
{
var match = Regex.Match(response, @"[-+]?\d+(?:\.\d+)?(?:[Ee][-+]?\d+)?");
if (!match.Success)
{
throw new InvalidOperationException($"{label} 측정값 파싱 실패");
}
return decimal.Parse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture);
}
}

84
Services/EquipmentMeasurementSettings.cs

@ -0,0 +1,84 @@
using System.IO;
namespace Housing.Services;
public sealed class EquipmentMeasurementSettings
{
public int Timeout { get; set; } = 5000;
public int SettleMilliseconds { get; set; } = 300;
public ScpiChannelSettings Voltage { get; set; } = new();
public ScpiChannelSettings Current { get; set; } = new();
public static EquipmentMeasurementSettings Load(string filePath)
{
if (!File.Exists(filePath))
{
throw new FileNotFoundException("Hardware.ini 파일을 찾을 수 없습니다.", filePath);
}
var values = IniFile.LoadSection(filePath, "Equipment");
return new EquipmentMeasurementSettings
{
Timeout = GetInt(values, "Timeout", 5000),
SettleMilliseconds = GetInt(values, "SettleMilliseconds", 300),
Voltage = LoadChannel(values, "Voltage", "MEAS:VOLT:DC?", "34460,34461,34465,34470,3446,3447"),
Current = LoadChannel(values, "Current", "MEAS:CURR? CH1", "E362")
};
}
private static ScpiChannelSettings LoadChannel(
Dictionary<string, string> values,
string prefix,
string defaultReadCommand,
string defaultIdnMatch)
{
return new ScpiChannelSettings
{
Connection = GetString(values, prefix + "Connection", string.Empty),
ResourceName = GetString(values, prefix + "Resource", string.Empty),
IdnMatch = GetString(values, prefix + "IdnMatch", defaultIdnMatch),
Host = GetString(values, prefix + "Host", string.Empty),
Port = GetInt(values, prefix + "Port", 5025),
PortName = GetString(values, prefix + "PortName", string.Empty),
BaudRate = GetInt(values, prefix + "BaudRate", 115200),
SetupCommand = GetString(values, prefix + "SetupCommand", string.Empty),
ReadCommand = GetString(values, prefix + "ReadCommand", defaultReadCommand)
};
}
private static string GetString(Dictionary<string, string> values, string key, string defaultValue)
{
return values.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value)
? value.Trim()
: defaultValue;
}
private static int GetInt(Dictionary<string, string> values, string key, int defaultValue)
{
return values.TryGetValue(key, out var value) && int.TryParse(value, out var result)
? result
: defaultValue;
}
}
public sealed class ScpiChannelSettings
{
public string Connection { get; set; } = string.Empty;
public string ResourceName { get; set; } = string.Empty;
public string IdnMatch { get; set; } = string.Empty;
public string Host { get; set; } = string.Empty;
public int Port { get; set; } = 5025;
public string PortName { get; set; } = string.Empty;
public int BaudRate { get; set; } = 115200;
public string SetupCommand { get; set; } = string.Empty;
public string ReadCommand { get; set; } = string.Empty;
public string[] GetIdnMatches()
{
return IdnMatch
.Split(',', ';')
.Select(value => value.Trim())
.Where(value => !string.IsNullOrWhiteSpace(value))
.ToArray();
}
}

130
Services/HousingAssemblyRepository.cs

@ -0,0 +1,130 @@
using System.Data;
using Housing.Models;
using Microsoft.Data.SqlClient;
namespace Housing.Services;
public sealed class HousingAssemblyRepository
{
private readonly DatabaseSettings _settings;
public HousingAssemblyRepository(DatabaseSettings settings)
{
_settings = settings;
}
public async Task InsertAsync(HousingAssemblyRecord record)
{
using var connection = new SqlConnection(CreateConnectionString());
using var command = connection.CreateCommand();
command.CommandText = @"
INSERT INTO dbo.Housing_Assembly
(
[IC_SN],
[PCB_Barcode],
[Maker],
[Model],
[Variant_1],
[Variant_2],
[Operator],
[Password],
[Production_Date],
[Line],
[Lot_No],
[Jig_No],
[PT_Vol_1],
[PT_Current_1],
[Result],
[Spare_1],
[Spare_2],
[Spare_3],
[Spare_4]
)
VALUES
(
@IC_SN,
@PCB_Barcode,
@Maker,
@Model,
@Variant_1,
@Variant_2,
@Operator,
@Password,
@Production_Date,
@Line,
@Lot_No,
@Jig_No,
@PT_Vol_1,
@PT_Current_1,
@Result,
@Spare_1,
@Spare_2,
@Spare_3,
@Spare_4
);";
AddNVarChar(command, "@IC_SN", 50, record.IcSn);
AddNVarChar(command, "@PCB_Barcode", 50, record.PcbBarcode);
AddNVarChar(command, "@Maker", 10, record.Maker);
AddNVarChar(command, "@Model", 10, record.Model);
AddNVarChar(command, "@Variant_1", 10, record.Variant1);
AddNVarChar(command, "@Variant_2", 10, record.Variant2);
AddNVarChar(command, "@Operator", 10, record.Operator);
AddNVarChar(command, "@Password", 10, record.Password);
command.Parameters.Add(new SqlParameter("@Production_Date", SqlDbType.DateTime2) { Value = record.ProductionDate });
AddNVarChar(command, "@Line", 5, record.Line);
AddNVarChar(command, "@Lot_No", 8, record.LotNo);
AddNVarChar(command, "@Jig_No", 10, record.JigNo);
AddDecimal(command, "@PT_Vol_1", record.PtVol1);
AddDecimal(command, "@PT_Current_1", record.PtCurrent1);
AddNVarChar(command, "@Result", 5, record.Result);
AddNVarChar(command, "@Spare_1", 30, record.Spare1);
AddNVarChar(command, "@Spare_2", 30, record.Spare2);
AddNVarChar(command, "@Spare_3", 30, record.Spare3);
AddNVarChar(command, "@Spare_4", 30, record.Spare4);
await connection.OpenAsync();
await command.ExecuteNonQueryAsync();
}
private string CreateConnectionString()
{
if (string.IsNullOrWhiteSpace(_settings.Ip) ||
string.IsNullOrWhiteSpace(_settings.Database) ||
string.IsNullOrWhiteSpace(_settings.DbId))
{
throw new InvalidOperationException("Database.ini의 IP, Database, DbId 값을 확인하세요.");
}
var builder = new SqlConnectionStringBuilder
{
DataSource = _settings.Ip,
InitialCatalog = _settings.Database,
UserID = _settings.DbId,
Password = _settings.DbPw,
Encrypt = _settings.Encrypt,
TrustServerCertificate = _settings.TrustServerCertificate,
ConnectTimeout = _settings.Timeout
};
return builder.ConnectionString;
}
private static void AddNVarChar(SqlCommand command, string name, int size, string value)
{
command.Parameters.Add(new SqlParameter(name, SqlDbType.NVarChar, size) { Value = value });
}
private static void AddDecimal(SqlCommand command, string name, decimal value)
{
var parameter = new SqlParameter(name, SqlDbType.Decimal)
{
Precision = 3,
Scale = 2,
Value = value
};
command.Parameters.Add(parameter);
}
}

7
Services/IScpiClient.cs

@ -0,0 +1,7 @@
namespace Housing.Services;
public interface IScpiClient : IDisposable
{
Task SendAsync(string command);
Task<string> QueryAsync(string command);
}

45
Services/IniFile.cs

@ -0,0 +1,45 @@
using System.IO;
namespace Housing.Services;
public static class IniFile
{
public static Dictionary<string, string> LoadSection(string filePath, string sectionName)
{
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var isTargetSection = false;
foreach (var rawLine in File.ReadAllLines(filePath))
{
var line = rawLine.Trim();
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(';') || line.StartsWith('#'))
{
continue;
}
if (line.StartsWith('[') && line.EndsWith(']'))
{
var currentSection = line.Substring(1, line.Length - 2).Trim();
isTargetSection = string.Equals(currentSection, sectionName, StringComparison.OrdinalIgnoreCase);
continue;
}
if (!isTargetSection)
{
continue;
}
var separatorIndex = line.IndexOf('=');
if (separatorIndex <= 0)
{
continue;
}
var key = line.Substring(0, separatorIndex).Trim();
var value = line.Substring(separatorIndex + 1).Trim();
values[key] = value;
}
return values;
}
}

58
Services/InspectionSettingsStore.cs

@ -0,0 +1,58 @@
using System.Globalization;
using System.IO;
using Housing.Models;
namespace Housing.Services;
public static class InspectionSettingsStore
{
public static InspectionJudgementSettings Load(string filePath)
{
if (!File.Exists(filePath))
{
var defaultSettings = new InspectionJudgementSettings();
Save(filePath, defaultSettings);
return defaultSettings;
}
var values = IniFile.LoadSection(filePath, "Judgement");
return new InspectionJudgementSettings
{
VMin = GetDecimal(values, "VMin", 0.00m),
VMax = GetDecimal(values, "VMax", 9.99m),
AMin = GetDecimal(values, "AMin", 0.00m),
AMax = GetDecimal(values, "AMax", 9.99m)
};
}
public static void Save(string filePath, InspectionJudgementSettings settings)
{
var lines = new[]
{
"[Judgement]",
$"VMin={Format(settings.VMin)}",
$"VMax={Format(settings.VMax)}",
$"AMin={Format(settings.AMin)}",
$"AMax={Format(settings.AMax)}"
};
File.WriteAllLines(filePath, lines);
}
private static decimal GetDecimal(Dictionary<string, string> values, string key, decimal defaultValue)
{
if (!values.TryGetValue(key, out var value))
{
return defaultValue;
}
return decimal.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out var result)
? result
: defaultValue;
}
private static string Format(decimal value)
{
return value.ToString("0.00", CultureInfo.InvariantCulture);
}
}

193
Services/SerialBoardClient.cs

@ -0,0 +1,193 @@
using System.IO.Ports;
using System.Text;
using System.Text.RegularExpressions;
namespace Housing.Services;
public sealed class SerialBoardClient : IDisposable
{
private readonly BoardHardwareSettings _settings;
private readonly SerialPort _serialPort;
public string PortName => _serialPort.PortName;
public SerialBoardClient(BoardHardwareSettings settings)
{
_settings = settings;
var portName = ResolvePortName(settings);
_serialPort = CreateSerialPort(portName, _settings);
}
public void Open()
{
if (!_serialPort.IsOpen)
{
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
}
}
public Task<string> SendCommandAsync(string command, int timeoutMilliseconds, bool waitForEndToken)
{
return Task.Run(() => SendCommand(command, timeoutMilliseconds, waitForEndToken));
}
private static SerialPort CreateSerialPort(string portName, BoardHardwareSettings settings)
{
return new SerialPort(portName, settings.BaudRate)
{
Encoding = Encoding.ASCII,
NewLine = "\r\n",
ReadTimeout = settings.ReadTimeout,
WriteTimeout = settings.ReadTimeout,
DtrEnable = true,
RtsEnable = true
};
}
private static string ResolvePortName(BoardHardwareSettings settings)
{
if (!IsAutoPort(settings.PortName))
{
return settings.PortName.Trim();
}
var portNames = GetOrderedPortNames();
if (portNames.Length == 0)
{
throw new InvalidOperationException("사용 가능한 COM 포트를 찾을 수 없습니다.");
}
foreach (var portName in portNames)
{
if (CanConnectBoard(portName, settings))
{
return portName;
}
}
throw new InvalidOperationException($"보드 자동 포트 검색 실패. 확인한 포트: {string.Join(", ", portNames)}");
}
private static bool IsAutoPort(string portName)
{
return string.IsNullOrWhiteSpace(portName) ||
string.Equals(portName.Trim(), "Auto", StringComparison.OrdinalIgnoreCase);
}
private static string[] GetOrderedPortNames()
{
return SerialPort.GetPortNames()
.OrderBy(GetPortNumber)
.ThenBy(portName => portName, StringComparer.OrdinalIgnoreCase)
.ToArray();
}
private static int GetPortNumber(string portName)
{
var match = Regex.Match(portName, @"\d+");
return match.Success && int.TryParse(match.Value, out var number)
? number
: int.MaxValue;
}
private static bool CanConnectBoard(string portName, BoardHardwareSettings settings)
{
try
{
using var probe = CreateSerialPort(portName, settings);
probe.Open();
probe.DiscardInBuffer();
probe.DiscardOutBuffer();
if (string.IsNullOrWhiteSpace(settings.ConnectCommand))
{
return true;
}
probe.Write(settings.ConnectCommand.Trim() + "\r\n");
var startedAt = DateTime.UtcNow;
while ((DateTime.UtcNow - startedAt).TotalMilliseconds < settings.ReadTimeout)
{
try
{
var line = probe.ReadLine();
if (IsSuccessLine(line))
{
return true;
}
if (!string.IsNullOrWhiteSpace(settings.EndToken) &&
line.Contains(settings.EndToken, StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
catch (TimeoutException)
{
return false;
}
}
}
catch
{
return false;
}
return false;
}
private static bool IsSuccessLine(string line)
{
return string.Equals(line.Trim(), "Success", StringComparison.OrdinalIgnoreCase);
}
private string SendCommand(string command, int timeoutMilliseconds, bool waitForEndToken)
{
if (string.IsNullOrWhiteSpace(command))
{
return string.Empty;
}
Open();
_serialPort.ReadTimeout = Math.Max(500, timeoutMilliseconds);
_serialPort.DiscardInBuffer();
_serialPort.Write(command.Trim() + "\r\n");
var startedAt = DateTime.UtcNow;
var response = new StringBuilder();
while ((DateTime.UtcNow - startedAt).TotalMilliseconds < timeoutMilliseconds)
{
try
{
var line = _serialPort.ReadLine();
response.AppendLine(line);
if (!waitForEndToken)
{
break;
}
if (line.Contains(_settings.EndToken, StringComparison.OrdinalIgnoreCase))
{
break;
}
}
catch (TimeoutException)
{
break;
}
}
return response.ToString();
}
public void Dispose()
{
_serialPort.Dispose();
}
}

132
Services/SerialScpiClient.cs

@ -0,0 +1,132 @@
using System.IO.Ports;
using System.Text;
using System.Text.RegularExpressions;
namespace Housing.Services;
public sealed class SerialScpiClient : IScpiClient
{
private readonly SerialPort _serialPort;
public string PortName => _serialPort.PortName;
public SerialScpiClient(string portName, int baudRate, int timeoutMilliseconds, IEnumerable<string>? idnMatches = null)
{
var resolvedPortName = ResolvePortName(portName, baudRate, timeoutMilliseconds, idnMatches);
_serialPort = CreateSerialPort(resolvedPortName, baudRate, timeoutMilliseconds);
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
}
public Task SendAsync(string command)
{
return Task.Run(() => _serialPort.Write(command.Trim() + "\n"));
}
public Task<string> QueryAsync(string command)
{
return Task.Run(() =>
{
_serialPort.DiscardInBuffer();
_serialPort.Write(command.Trim() + "\n");
return _serialPort.ReadLine().Trim();
});
}
private static SerialPort CreateSerialPort(string portName, int baudRate, int timeoutMilliseconds)
{
return new SerialPort(portName, baudRate)
{
Encoding = Encoding.ASCII,
NewLine = "\n",
ReadTimeout = timeoutMilliseconds,
WriteTimeout = timeoutMilliseconds,
DtrEnable = true,
RtsEnable = true
};
}
private static string ResolvePortName(string portName, int baudRate, int timeoutMilliseconds, IEnumerable<string>? idnMatches)
{
if (!IsAutoPort(portName))
{
return portName.Trim();
}
var portNames = SerialPort.GetPortNames()
.OrderBy(GetPortNumber)
.ThenBy(candidate => candidate, StringComparer.OrdinalIgnoreCase)
.ToArray();
if (portNames.Length == 0)
{
throw new InvalidOperationException("사용 가능한 장비 COM 포트를 찾을 수 없습니다.");
}
var tokens = NormalizeIdnMatches(idnMatches);
if (tokens.Length == 0 && portNames.Length == 1)
{
return portNames[0];
}
foreach (var candidate in portNames)
{
if (MatchesIdn(candidate, baudRate, timeoutMilliseconds, tokens))
{
return candidate;
}
}
throw new InvalidOperationException($"SCPI 장비 자동 포트 검색 실패. 확인한 포트: {string.Join(", ", portNames)}");
}
private static bool IsAutoPort(string portName)
{
return string.IsNullOrWhiteSpace(portName) ||
string.Equals(portName.Trim(), "Auto", StringComparison.OrdinalIgnoreCase);
}
private static int GetPortNumber(string portName)
{
var match = Regex.Match(portName, @"\d+");
return match.Success && int.TryParse(match.Value, out var number)
? number
: int.MaxValue;
}
private static string[] NormalizeIdnMatches(IEnumerable<string>? idnMatches)
{
return idnMatches?
.SelectMany(value => value.Split(',', ';'))
.Select(value => value.Trim())
.Where(value => !string.IsNullOrWhiteSpace(value))
.ToArray() ?? Array.Empty<string>();
}
private static bool MatchesIdn(string portName, int baudRate, int timeoutMilliseconds, string[] idnMatches)
{
try
{
using var probe = CreateSerialPort(portName, baudRate, timeoutMilliseconds);
probe.Open();
probe.DiscardInBuffer();
probe.DiscardOutBuffer();
probe.Write("*IDN?\n");
var idn = probe.ReadLine().Trim();
return idnMatches.Length == 0 ||
idnMatches.Any(token => idn.Contains(token, StringComparison.OrdinalIgnoreCase));
}
catch
{
return false;
}
}
public void Dispose()
{
_serialPort.Dispose();
}
}

92
Services/TcpScpiClient.cs

@ -0,0 +1,92 @@
using System.Net.Sockets;
using System.Text;
namespace Housing.Services;
public sealed class TcpScpiClient : IScpiClient
{
private readonly TcpClient _tcpClient;
private readonly NetworkStream _stream;
private readonly int _timeoutMilliseconds;
private TcpScpiClient(TcpClient tcpClient, int timeoutMilliseconds)
{
_tcpClient = tcpClient;
_stream = _tcpClient.GetStream();
_timeoutMilliseconds = timeoutMilliseconds;
}
public static async Task<TcpScpiClient> ConnectAsync(string host, int port, int timeoutMilliseconds)
{
var tcpClient = new TcpClient();
using var cancellation = new CancellationTokenSource(timeoutMilliseconds);
try
{
await tcpClient.ConnectAsync(host, port, cancellation.Token);
}
catch (OperationCanceledException)
{
tcpClient.Dispose();
throw new TimeoutException($"{host}:{port} 장비 연결 시간이 초과되었습니다.");
}
catch
{
tcpClient.Dispose();
throw;
}
return new TcpScpiClient(tcpClient, timeoutMilliseconds);
}
public async Task SendAsync(string command)
{
using var cancellation = new CancellationTokenSource(_timeoutMilliseconds);
var bytes = Encoding.ASCII.GetBytes(command.Trim() + "\n");
await _stream.WriteAsync(bytes, cancellation.Token);
await _stream.FlushAsync(cancellation.Token);
}
public async Task<string> QueryAsync(string command)
{
await SendAsync(command);
using var cancellation = new CancellationTokenSource(_timeoutMilliseconds);
var buffer = new byte[1024];
var response = new StringBuilder();
while (true)
{
int bytesRead;
try
{
bytesRead = await _stream.ReadAsync(buffer, cancellation.Token);
}
catch (OperationCanceledException)
{
throw new TimeoutException($"{command} 응답 시간이 초과되었습니다.");
}
if (bytesRead == 0)
{
break;
}
var chunk = Encoding.ASCII.GetString(buffer, 0, bytesRead);
response.Append(chunk);
if (chunk.Contains('\n'))
{
break;
}
}
return response.ToString().Trim();
}
public void Dispose()
{
_stream.Dispose();
_tcpClient.Dispose();
}
}

214
Services/VisaScpiClient.cs

@ -0,0 +1,214 @@
using System.Collections;
namespace Housing.Services;
public sealed class VisaScpiClient : IScpiClient
{
private readonly dynamic _io;
private VisaScpiClient(dynamic io, string resourceName)
{
_io = io;
ResourceName = resourceName;
}
public string ResourceName { get; }
public static Task<VisaScpiClient> OpenAsync(string resourceName, int timeoutMilliseconds)
{
return Task.Run(() => Open(resourceName, timeoutMilliseconds));
}
public static Task<VisaScpiClient> OpenMatchingAsync(
string resourceName,
IEnumerable<string> idnMatches,
int timeoutMilliseconds)
{
return string.IsNullOrWhiteSpace(resourceName)
? Task.Run(() => OpenFirstMatching(idnMatches, timeoutMilliseconds))
: OpenAsync(resourceName, timeoutMilliseconds);
}
private static VisaScpiClient Open(string resourceName, int timeoutMilliseconds)
{
if (string.IsNullOrWhiteSpace(resourceName))
{
throw new InvalidOperationException("장비 VISA Resource 값을 확인하세요.");
}
var (resourceManagerType, formattedIoType) = GetVisaComTypes();
dynamic resourceManager = Activator.CreateInstance(resourceManagerType)!;
return OpenResource(resourceManager, formattedIoType, resourceName.Trim(), timeoutMilliseconds);
}
private static VisaScpiClient OpenFirstMatching(IEnumerable<string> idnMatches, int timeoutMilliseconds)
{
var tokens = NormalizeIdnMatches(idnMatches);
var (resourceManagerType, formattedIoType) = GetVisaComTypes();
dynamic resourceManager = Activator.CreateInstance(resourceManagerType)!;
var resourceNames = FindResourceNames(resourceManager);
if (resourceNames.Length == 0)
{
throw new InvalidOperationException("VISA 장비를 찾을 수 없습니다. USB/LAN 장비 연결과 VISA 드라이버 설치를 확인하세요.");
}
var checkedResources = new List<string>();
foreach (var resourceName in resourceNames)
{
VisaScpiClient? client = null;
try
{
client = OpenResource(resourceManager, formattedIoType, resourceName, timeoutMilliseconds);
var idn = client.Query("*IDN?");
checkedResources.Add($"{resourceName}: {idn}");
if (tokens.Length == 0 ||
tokens.Any(token => idn.Contains(token, StringComparison.OrdinalIgnoreCase)))
{
return client;
}
}
catch (Exception ex)
{
checkedResources.Add($"{resourceName}: {ex.Message}");
}
client?.Dispose();
}
var tokenMessage = tokens.Length == 0 ? string.Empty : $" IDN 키워드: {string.Join(", ", tokens)}.";
var checkedMessage = checkedResources.Count == 0
? string.Empty
: $" 확인 결과: {string.Join(" / ", checkedResources)}";
throw new InvalidOperationException($"VISA 장비 자동 검색 실패.{tokenMessage}{checkedMessage}");
}
private static (Type ResourceManagerType, Type FormattedIoType) GetVisaComTypes()
{
var resourceManagerType = Type.GetTypeFromProgID("VISA.GlobalRM") ??
Type.GetTypeFromProgID("VisaComLib.ResourceManager");
var formattedIoType = Type.GetTypeFromProgID("VISA.FormattedIO488") ??
Type.GetTypeFromProgID("VisaComLib.FormattedIO488");
if (resourceManagerType is null || formattedIoType is null)
{
throw new InvalidOperationException("VISA 라이브러리를 찾을 수 없습니다. Keysight IO Libraries 또는 NI-VISA 설치가 필요합니다.");
}
return (resourceManagerType, formattedIoType);
}
private static VisaScpiClient OpenResource(
dynamic resourceManager,
Type formattedIoType,
string resourceName,
int timeoutMilliseconds)
{
dynamic session = resourceManager.Open(resourceName);
try
{
session.Timeout = timeoutMilliseconds;
}
catch
{
// Some VISA COM sessions expose timeout through driver-specific properties only.
}
dynamic formattedIo = Activator.CreateInstance(formattedIoType)!;
formattedIo.IO = session;
return new VisaScpiClient(formattedIo, resourceName);
}
private static string[] FindResourceNames(dynamic resourceManager)
{
var resourceNames = new SortedSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var pattern in new[] { "?*INSTR", "USB?*INSTR", "TCPIP?*INSTR", "GPIB?*INSTR", "ASRL?*INSTR" })
{
try
{
AddResourceNames(resourceNames, resourceManager.FindRsrc(pattern));
}
catch
{
// Resource discovery support differs by VISA COM implementation and backend.
}
}
return resourceNames.ToArray();
}
private static void AddResourceNames(ISet<string> resourceNames, object? value)
{
switch (value)
{
case null:
return;
case string resourceName:
AddResourceName(resourceNames, resourceName);
return;
case IEnumerable enumerable:
foreach (var item in enumerable)
{
AddResourceName(resourceNames, item?.ToString());
}
return;
default:
AddResourceName(resourceNames, value.ToString());
return;
}
}
private static void AddResourceName(ISet<string> resourceNames, string? resourceName)
{
if (!string.IsNullOrWhiteSpace(resourceName))
{
resourceNames.Add(resourceName.Trim());
}
}
private static string[] NormalizeIdnMatches(IEnumerable<string> idnMatches)
{
return idnMatches
.SelectMany(value => value.Split(',', ';'))
.Select(value => value.Trim())
.Where(value => !string.IsNullOrWhiteSpace(value))
.ToArray();
}
public Task SendAsync(string command)
{
return Task.Run(() => Send(command));
}
public Task<string> QueryAsync(string command)
{
return Task.Run(() => Query(command));
}
private void Send(string command)
{
_io.WriteString(command.Trim() + "\n", true);
}
private string Query(string command)
{
Send(command);
return ((string)_io.ReadString()).Trim();
}
public void Dispose()
{
try
{
_io.IO.Close();
}
catch
{
// Closing is best-effort because VISA COM implementations differ by vendor.
}
}
}

23
bin/Debug/net10.0-windows/Housing.deps.json

@ -0,0 +1,23 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"Housing/1.0.0": {
"runtime": {
"Housing.dll": {}
}
}
}
},
"libraries": {
"Housing/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

BIN
bin/Debug/net10.0-windows/Housing.dll

Binary file not shown.

BIN
bin/Debug/net10.0-windows/Housing.exe

Binary file not shown.

BIN
bin/Debug/net10.0-windows/Housing.pdb

Binary file not shown.

19
bin/Debug/net10.0-windows/Housing.runtimeconfig.json

@ -0,0 +1,19 @@
{
"runtimeOptions": {
"tfm": "net10.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "10.0.0"
},
{
"name": "Microsoft.WindowsDesktop.App",
"version": "10.0.0"
}
],
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false,
"CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false
}
}
}

BIN
bin/Debug/net9.0-windows/Azure.Core.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Azure.Identity.dll

Binary file not shown.

8
bin/Debug/net9.0-windows/Database.ini

@ -0,0 +1,8 @@
[Database]
IP=127.0.0.1
Database=Housing
DbId=sa
DbPw=your_password
Encrypt=True
TrustServerCertificate=True
Timeout=5

44
bin/Debug/net9.0-windows/Hardware.ini

@ -0,0 +1,44 @@
[Board]
PortName=Auto
BaudRate=115200
ReadTimeout=5000
ConnectCommand=x00c_001101:owt28006727ea97c7801
ReadIdCommand=x00c_001101:ow2800326003e
CalDefaultCommand=x00c_001001
EndToken=<end>
[Equipment]
; 목표: 장비 화면에 표시되는 현재 측정값을 읽습니다.
; V 출력: Keysight 34465A DMM 값
; A 출력: Keysight E36233A Power Supply CH1 Current 값
; USB 장비는 Keysight Connection Expert 또는 NI MAX에서 보이는 VISA 주소를 Resource에 넣으세요.
; 예: USB0::0x2A8D::0x1301::MY12345678::INSTR
Timeout=5000
SettleMilliseconds=300
; 34465A DMM
VoltageConnection=Visa
VoltageResource=
VoltageIdnMatch=34460,34461,34465,34470,3446,3447
VoltageSetupCommand=
VoltageReadCommand=MEAS:VOLT:DC?
; E36233A Power Supply
CurrentConnection=Visa
CurrentResource=
CurrentIdnMatch=E362
CurrentSetupCommand=
CurrentReadCommand=MEAS:CURR? CH1
; COM 포트로 잡히는 장비 예시:
; VoltageConnection=Serial
; VoltagePortName=Auto
; VoltageBaudRate=115200
; LAN 장비 예시:
; VoltageConnection=Tcp
; VoltageHost=192.168.0.10
; VoltagePort=5025
; E36233A 파워서플라이에서 CH1 전압까지 읽고 싶을 때 예시:
; VoltageReadCommand=MEAS:VOLT? CH1

835
bin/Debug/net9.0-windows/Housing.deps.json

@ -0,0 +1,835 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v9.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v9.0": {
"Housing/1.0.0": {
"dependencies": {
"Microsoft.Data.SqlClient": "6.1.3",
"System.IO.Ports": "9.0.10"
},
"runtime": {
"Housing.dll": {}
}
},
"Azure.Core/1.47.1": {
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
"System.ClientModel": "1.5.1",
"System.Memory.Data": "8.0.1"
},
"runtime": {
"lib/net8.0/Azure.Core.dll": {
"assemblyVersion": "1.47.1.0",
"fileVersion": "1.4700.125.36505"
}
}
},
"Azure.Identity/1.14.2": {
"dependencies": {
"Azure.Core": "1.47.1",
"Microsoft.Identity.Client": "4.73.1",
"Microsoft.Identity.Client.Extensions.Msal": "4.73.1"
},
"runtime": {
"lib/net8.0/Azure.Identity.dll": {
"assemblyVersion": "1.14.2.0",
"fileVersion": "1.1400.225.36004"
}
}
},
"Microsoft.Bcl.AsyncInterfaces/8.0.0": {
"runtime": {
"lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": {
"assemblyVersion": "8.0.0.0",
"fileVersion": "8.0.23.53103"
}
}
},
"Microsoft.Bcl.Cryptography/9.0.4": {
"runtime": {
"lib/net9.0/Microsoft.Bcl.Cryptography.dll": {
"assemblyVersion": "9.0.0.4",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Data.SqlClient/6.1.3": {
"dependencies": {
"Azure.Core": "1.47.1",
"Azure.Identity": "1.14.2",
"Microsoft.Bcl.Cryptography": "9.0.4",
"Microsoft.Data.SqlClient.SNI.runtime": "6.0.2",
"Microsoft.Extensions.Caching.Memory": "9.0.4",
"Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1",
"Microsoft.SqlServer.Server": "1.0.0"
},
"runtime": {
"lib/net9.0/Microsoft.Data.SqlClient.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.13.25316.3"
}
},
"resources": {
"lib/net9.0/cs/Microsoft.Data.SqlClient.resources.dll": {
"locale": "cs"
},
"lib/net9.0/de/Microsoft.Data.SqlClient.resources.dll": {
"locale": "de"
},
"lib/net9.0/es/Microsoft.Data.SqlClient.resources.dll": {
"locale": "es"
},
"lib/net9.0/fr/Microsoft.Data.SqlClient.resources.dll": {
"locale": "fr"
},
"lib/net9.0/it/Microsoft.Data.SqlClient.resources.dll": {
"locale": "it"
},
"lib/net9.0/ja/Microsoft.Data.SqlClient.resources.dll": {
"locale": "ja"
},
"lib/net9.0/ko/Microsoft.Data.SqlClient.resources.dll": {
"locale": "ko"
},
"lib/net9.0/pl/Microsoft.Data.SqlClient.resources.dll": {
"locale": "pl"
},
"lib/net9.0/pt-BR/Microsoft.Data.SqlClient.resources.dll": {
"locale": "pt-BR"
},
"lib/net9.0/ru/Microsoft.Data.SqlClient.resources.dll": {
"locale": "ru"
},
"lib/net9.0/tr/Microsoft.Data.SqlClient.resources.dll": {
"locale": "tr"
},
"lib/net9.0/zh-Hans/Microsoft.Data.SqlClient.resources.dll": {
"locale": "zh-Hans"
},
"lib/net9.0/zh-Hant/Microsoft.Data.SqlClient.resources.dll": {
"locale": "zh-Hant"
}
},
"runtimeTargets": {
"runtimes/unix/lib/net9.0/Microsoft.Data.SqlClient.dll": {
"rid": "unix",
"assetType": "runtime",
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.13.25316.3"
},
"runtimes/win/lib/net9.0/Microsoft.Data.SqlClient.dll": {
"rid": "win",
"assetType": "runtime",
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.13.25316.3"
}
}
},
"Microsoft.Data.SqlClient.SNI.runtime/6.0.2": {
"runtimeTargets": {
"runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.dll": {
"rid": "win-arm64",
"assetType": "native",
"fileVersion": "6.2.0.0"
},
"runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.dll": {
"rid": "win-x64",
"assetType": "native",
"fileVersion": "6.2.0.0"
},
"runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.dll": {
"rid": "win-x86",
"assetType": "native",
"fileVersion": "6.2.0.0"
}
}
},
"Microsoft.Extensions.Caching.Abstractions/9.0.4": {
"dependencies": {
"Microsoft.Extensions.Primitives": "9.0.4"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Extensions.Caching.Memory/9.0.4": {
"dependencies": {
"Microsoft.Extensions.Caching.Abstractions": "9.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.4",
"Microsoft.Extensions.Logging.Abstractions": "9.0.4",
"Microsoft.Extensions.Options": "9.0.4",
"Microsoft.Extensions.Primitives": "9.0.4"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Caching.Memory.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/9.0.4": {
"runtime": {
"lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/9.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.4"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Extensions.Options/9.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.4",
"Microsoft.Extensions.Primitives": "9.0.4"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Extensions.Primitives/9.0.4": {
"runtime": {
"lib/net9.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.425.16305"
}
}
},
"Microsoft.Identity.Client/4.73.1": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.Identity.Client.dll": {
"assemblyVersion": "4.73.1.0",
"fileVersion": "4.73.1.0"
}
}
},
"Microsoft.Identity.Client.Extensions.Msal/4.73.1": {
"dependencies": {
"Microsoft.Identity.Client": "4.73.1"
},
"runtime": {
"lib/net8.0/Microsoft.Identity.Client.Extensions.Msal.dll": {
"assemblyVersion": "4.73.1.0",
"fileVersion": "4.73.1.0"
}
}
},
"Microsoft.IdentityModel.Abstractions/7.7.1": {
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"Microsoft.IdentityModel.Logging/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"Microsoft.IdentityModel.Protocols/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Protocols.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.Protocols": "7.7.1",
"System.IdentityModel.Tokens.Jwt": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"Microsoft.IdentityModel.Tokens/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "7.7.1"
},
"runtime": {
"lib/net8.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"Microsoft.SqlServer.Server/1.0.0": {
"runtime": {
"lib/netstandard2.0/Microsoft.SqlServer.Server.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"runtime.android-arm.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/android-arm/native/libSystem.IO.Ports.Native.so": {
"rid": "android-arm",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.android-arm64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/android-arm64/native/libSystem.IO.Ports.Native.so": {
"rid": "android-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.android-x64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/android-x64/native/libSystem.IO.Ports.Native.so": {
"rid": "android-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.android-x86.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/android-x86/native/libSystem.IO.Ports.Native.so": {
"rid": "android-x86",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-arm.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-arm/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-arm",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-arm64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-arm64/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-bionic-arm64/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-bionic-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-bionic-x64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-bionic-x64/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-bionic-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-musl-arm.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-musl-arm/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-musl-arm",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-musl-arm64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-musl-arm64/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-musl-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-musl-x64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-musl-x64/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-musl-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.linux-x64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/linux-x64/native/libSystem.IO.Ports.Native.so": {
"rid": "linux-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/maccatalyst-arm64/native/libSystem.IO.Ports.Native.dylib": {
"rid": "maccatalyst-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.maccatalyst-x64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/maccatalyst-x64/native/libSystem.IO.Ports.Native.dylib": {
"rid": "maccatalyst-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.native.System.IO.Ports/9.0.10": {
"dependencies": {
"runtime.android-arm.runtime.native.System.IO.Ports": "9.0.10",
"runtime.android-arm64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.android-x64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.android-x86.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-arm.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-arm64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-bionic-arm64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-bionic-x64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-musl-arm.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-musl-arm64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-musl-x64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.linux-x64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.maccatalyst-arm64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.maccatalyst-x64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.osx-arm64.runtime.native.System.IO.Ports": "9.0.10",
"runtime.osx-x64.runtime.native.System.IO.Ports": "9.0.10"
}
},
"runtime.osx-arm64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/osx-arm64/native/libSystem.IO.Ports.Native.dylib": {
"rid": "osx-arm64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"runtime.osx-x64.runtime.native.System.IO.Ports/9.0.10": {
"runtimeTargets": {
"runtimes/osx-x64/native/libSystem.IO.Ports.Native.dylib": {
"rid": "osx-x64",
"assetType": "native",
"fileVersion": "0.0.0.0"
}
}
},
"System.ClientModel/1.5.1": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "9.0.4",
"System.Memory.Data": "8.0.1"
},
"runtime": {
"lib/net8.0/System.ClientModel.dll": {
"assemblyVersion": "1.5.1.0",
"fileVersion": "1.500.125.36405"
}
}
},
"System.IdentityModel.Tokens.Jwt/7.7.1": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "7.7.1",
"Microsoft.IdentityModel.Tokens": "7.7.1"
},
"runtime": {
"lib/net8.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "7.7.1.0",
"fileVersion": "7.7.1.50719"
}
}
},
"System.IO.Ports/9.0.10": {
"dependencies": {
"runtime.native.System.IO.Ports": "9.0.10"
},
"runtime": {
"lib/net9.0/System.IO.Ports.dll": {
"assemblyVersion": "9.0.0.10",
"fileVersion": "9.0.1025.47515"
}
},
"runtimeTargets": {
"runtimes/unix/lib/net9.0/System.IO.Ports.dll": {
"rid": "unix",
"assetType": "runtime",
"assemblyVersion": "9.0.0.10",
"fileVersion": "9.0.1025.47515"
},
"runtimes/win/lib/net9.0/System.IO.Ports.dll": {
"rid": "win",
"assetType": "runtime",
"assemblyVersion": "9.0.0.10",
"fileVersion": "9.0.1025.47515"
}
}
},
"System.Memory.Data/8.0.1": {
"runtime": {
"lib/net8.0/System.Memory.Data.dll": {
"assemblyVersion": "8.0.0.1",
"fileVersion": "8.0.1024.46610"
}
}
}
}
},
"libraries": {
"Housing/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Azure.Core/1.47.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-oPcncSsDHuxB8SC522z47xbp2+ttkcKv2YZ90KXhRKN0YQd2+7l1UURT9EBzUNEXtkLZUOAB5xbByMTrYRh3yA==",
"path": "azure.core/1.47.1",
"hashPath": "azure.core.1.47.1.nupkg.sha512"
},
"Azure.Identity/1.14.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-YhNMwOTwT+I2wIcJKSdP0ADyB2aK+JaYWZxO8LSRDm5w77LFr0ykR9xmt2ZV5T1gaI7xU6iNFIh/yW1dAlpddQ==",
"path": "azure.identity/1.14.2",
"hashPath": "azure.identity.1.14.2.nupkg.sha512"
},
"Microsoft.Bcl.AsyncInterfaces/8.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
"path": "microsoft.bcl.asyncinterfaces/8.0.0",
"hashPath": "microsoft.bcl.asyncinterfaces.8.0.0.nupkg.sha512"
},
"Microsoft.Bcl.Cryptography/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-YgZYAWzyNuPVtPq6WNm0bqOWNjYaWgl5mBWTGZyNoXitYBUYSp6iUB9AwK0V1mo793qRJUXz2t6UZrWITZSvuQ==",
"path": "microsoft.bcl.cryptography/9.0.4",
"hashPath": "microsoft.bcl.cryptography.9.0.4.nupkg.sha512"
},
"Microsoft.Data.SqlClient/6.1.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ys/z8Tx8074CDU20EilNvBRJuJdwKSthpHkzUpt3JghnjB6GjbZusoOcCtNbhPCCWsEJqN8bxaT7HnS3UZuUDQ==",
"path": "microsoft.data.sqlclient/6.1.3",
"hashPath": "microsoft.data.sqlclient.6.1.3.nupkg.sha512"
},
"Microsoft.Data.SqlClient.SNI.runtime/6.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-f+pRODTWX7Y67jXO3T5S2dIPZ9qMJNySjlZT/TKmWVNWe19N8jcWmHaqHnnchaq3gxEKv1SWVY5EFzOD06l41w==",
"path": "microsoft.data.sqlclient.sni.runtime/6.0.2",
"hashPath": "microsoft.data.sqlclient.sni.runtime.6.0.2.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Abstractions/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-imcZ5BGhBw5mNsWLepBbqqumWaFe0GtvyCvne2/2wsDIBRa2+Lhx4cU/pKt/4BwOizzUEOls2k1eOJQXHGMalg==",
"path": "microsoft.extensions.caching.abstractions/9.0.4",
"hashPath": "microsoft.extensions.caching.abstractions.9.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Memory/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-G5rEq1Qez5VJDTEyRsRUnewAspKjaY57VGsdZ8g8Ja6sXXzoiI3PpTd1t43HjHqNWD5A06MQveb2lscn+2CU+w==",
"path": "microsoft.extensions.caching.memory/9.0.4",
"hashPath": "microsoft.extensions.caching.memory.9.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UI0TQPVkS78bFdjkTodmkH0Fe8lXv9LnhGFKgKrsgUJ5a5FVdFRcgjIkBVLbGgdRhxWirxH/8IXUtEyYJx6GQg==",
"path": "microsoft.extensions.dependencyinjection.abstractions/9.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-0MXlimU4Dud6t+iNi5NEz3dO2w1HXdhoOLaYFuLPCjAsvlPQGwOT6V2KZRMLEhCAm/stSZt1AUv0XmDdkjvtbw==",
"path": "microsoft.extensions.logging.abstractions/9.0.4",
"hashPath": "microsoft.extensions.logging.abstractions.9.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Options/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fiFI2+58kicqVZyt/6obqoFwHiab7LC4FkQ3mmiBJ28Yy4fAvy2+v9MRnSvvlOO8chTOjKsdafFl/K9veCPo5g==",
"path": "microsoft.extensions.options/9.0.4",
"hashPath": "microsoft.extensions.options.9.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/9.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SPFyMjyku1nqTFFJ928JAMd0QnRe4xjE7KeKnZMWXf3xk+6e0WiOZAluYtLdbJUXtsl2cCRSi8cBquJ408k8RA==",
"path": "microsoft.extensions.primitives/9.0.4",
"hashPath": "microsoft.extensions.primitives.9.0.4.nupkg.sha512"
},
"Microsoft.Identity.Client/4.73.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NnDLS8QwYqO5ZZecL2oioi1LUqjh5Ewk4bMLzbgiXJbQmZhDLtKwLxL3DpGMlQAJ2G4KgEnvGPKa+OOgffeJbw==",
"path": "microsoft.identity.client/4.73.1",
"hashPath": "microsoft.identity.client.4.73.1.nupkg.sha512"
},
"Microsoft.Identity.Client.Extensions.Msal/4.73.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xDztAiV2F0wI0W8FLKv5cbaBefyLD6JVaAsvgSN7bjWNCzGYzHbcOEIP5s4TJXUpQzMfUyBsFl1mC6Zmgpz0PQ==",
"path": "microsoft.identity.client.extensions.msal/4.73.1",
"hashPath": "microsoft.identity.client.extensions.msal.4.73.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-S7sHg6gLg7oFqNGLwN1qSbJDI+QcRRj8SuJ1jHyCmKSipnF6ZQL+tFV2NzVfGj/xmGT9TykQdQiBN+p5Idl4TA==",
"path": "microsoft.identitymodel.abstractions/7.7.1",
"hashPath": "microsoft.identitymodel.abstractions.7.7.1.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3Izi75UCUssvo8LPx3OVnEeZay58qaFicrtSnbtUt7q8qQi0gy46gh4V8VUTkMVMKXV6VMyjBVmeNNgeCUJuIw==",
"path": "microsoft.identitymodel.jsonwebtokens/7.7.1",
"hashPath": "microsoft.identitymodel.jsonwebtokens.7.7.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BZNgSq/o8gsKExdYoBKPR65fdsxW0cTF8PsdqB8y011AGUJJW300S/ZIsEUD0+sOmGc003Gwv3FYbjrVjvsLNQ==",
"path": "microsoft.identitymodel.logging/7.7.1",
"hashPath": "microsoft.identitymodel.logging.7.7.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Protocols/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-h+fHHBGokepmCX+QZXJk4Ij8OApCb2n2ktoDkNX5CXteXsOxTHMNgjPGpAwdJMFvAL7TtGarUnk3o97NmBq2QQ==",
"path": "microsoft.identitymodel.protocols/7.7.1",
"hashPath": "microsoft.identitymodel.protocols.7.7.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Protocols.OpenIdConnect/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==",
"path": "microsoft.identitymodel.protocols.openidconnect/7.7.1",
"hashPath": "microsoft.identitymodel.protocols.openidconnect.7.7.1.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fQ0VVCba75lknUHGldi3iTKAYUQqbzp1Un8+d9cm9nON0Gs8NAkXddNg8iaUB0qi/ybtAmNWizTR4avdkCJ9pQ==",
"path": "microsoft.identitymodel.tokens/7.7.1",
"hashPath": "microsoft.identitymodel.tokens.7.7.1.nupkg.sha512"
},
"Microsoft.SqlServer.Server/1.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==",
"path": "microsoft.sqlserver.server/1.0.0",
"hashPath": "microsoft.sqlserver.server.1.0.0.nupkg.sha512"
},
"runtime.android-arm.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-KUeHD0wRFCTS9QHantD5Cv/RzDzVY/mQP1Z/eKLtlX5A5SZvsqeomAoayPdh/QmgSzquoHeIDMAMp8VVU+Xzag==",
"path": "runtime.android-arm.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.android-arm.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.android-arm64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-b+z8JoBrZ5TMXiXeh0s+s9/uIVx6PmulEuMaN81JLM68aAb4DWHi7t5CL+8bWJhsFhd8VAYoZ9pi5miNTFPeuA==",
"path": "runtime.android-arm64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.android-arm64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.android-x64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-K7u+/G2gPoRLNc974p1Tnp44VRLlpQWZrKEQofBTpyJZPgd46ayvXayqT4jyGodG4O6Q6+yY2pYUYlqv1K2l6w==",
"path": "runtime.android-x64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.android-x64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.android-x86.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-TGT4P40ockzrZf/K46A3VAl2dC2PWAS6WhqqtZJbH5G7XgBMX/FoaoY6DtFtz6u7RVl4zhjdG3QWXEv/u/1Hlg==",
"path": "runtime.android-x86.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.android-x86.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-arm.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Y2EEaUtO1JolypkFcqgsDxjmOleHa7d9OxBY4Osw5vIdQpOfP0Qj30czQfkN7cZTQH8NxsSr5WawVbk5yFabFg==",
"path": "runtime.linux-arm.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-arm.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-arm64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-nIFQGoz22wdgtmS4Ce+weqGUBh1kpO4XbNEgCU01+7P/+yZAb+gbRSeJUyUmCPhyW0S8FhX1xgJDH/SiJgP05Q==",
"path": "runtime.linux-arm64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-arm64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-bionic-arm64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-jV3esGC4j69yPlRzj50EbJq4syweBm4rOWKYJ3nWCMbVzTW1YQ2o4QhiVjCDOEKEf6q5eVGEaa6fyVXQ/K95Hw==",
"path": "runtime.linux-bionic-arm64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-bionic-arm64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-bionic-x64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UfoiSWuf75mYJPknRXSezDoFYaCp5dWoUjASjg6gQSa7FD2G59Mee6vMEzHFS+x8N+H8oNnL9TCIZUD4/8e/2Q==",
"path": "runtime.linux-bionic-x64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-bionic-x64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-musl-arm.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-CWwqjMVVtYiW4I9wk9YuUaSxxkPZKZ/BKj5ppAsIZv4X9u/dyh8+Qbj3Fly61uUXpGxXU4QFQhYuPi5pJTAOBA==",
"path": "runtime.linux-musl-arm.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-musl-arm.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-musl-arm64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NxMtoYPV8lreQggsXWsXXRF/djycKieThc4O2kxGB6EgjsiRDuNdnbODV0lWGV6v4mn08uQvuOhmBP5ZYpVdkA==",
"path": "runtime.linux-musl-arm64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-musl-arm64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-musl-x64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZNQ/D4lUGxTbfGAZRWP4vp7tCLqvInit03YXAiFXDWh/DnMEosBjrwcu8vbWgSsF01DUbyZQai8lwAStIZWo8w==",
"path": "runtime.linux-musl-x64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-musl-x64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.linux-x64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-mOTksL8qwN9EiWz71Dzhc98iQhKmtHlWH5GbhiCJ+ES2ei1HLr2bXSNMrXRd5s0Wfzg6xeQmT5M9umcgtv8Bzg==",
"path": "runtime.linux-x64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.linux-x64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.maccatalyst-arm64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-aKoLfCdLoQGhPh2VYBn6sn1kDuwgtXKJ4D2Ql/2WLCGCuXestpxLBS0JhSVBFSp1HrFdazj4aSwpYurtes+1Gg==",
"path": "runtime.maccatalyst-arm64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.maccatalyst-arm64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.maccatalyst-x64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-B+boSbUptH2fiKiUXBIu5hlQ3oH+nAdPY9TNmpU10nuoFW/DNz21fCXY3UOIz9oRXp5Ao2b7RlurgpBl0AgoOQ==",
"path": "runtime.maccatalyst-x64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.maccatalyst-x64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-7AzXN+J8PkTVctfymH+tEaAmj0wNKFPyACqp5cYff0DrHxnsQhv7xtRWxJRrQ0azOAFGR1mhWN4aM1QkbQQ0Rw==",
"path": "runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.osx-arm64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-m+gRRrmCTwP30YiVnFeZg/zRWgzVcOlN28cIPMkK11C9UU60waLknTnRLlQUagIkWaCDifKJCB6wtEeca5QiMA==",
"path": "runtime.osx-arm64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.osx-arm64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"runtime.osx-x64.runtime.native.System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-89HgF1Oplzjomn0BLeqJxEC17d//zmbs7CMKT12ZvjvFMvpMFO8uQUZ9xRIh91rM0ByfbhSobe2IRezjpeDNlg==",
"path": "runtime.osx-x64.runtime.native.system.io.ports/9.0.10",
"hashPath": "runtime.osx-x64.runtime.native.system.io.ports.9.0.10.nupkg.sha512"
},
"System.ClientModel/1.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-k2jKSO0X45IqhVOT9iQB4xralNN9foRQsRvXBTyRpAVxyzCJlG895T9qYrQWbcJ6OQXxOouJQ37x5nZH5XKK+A==",
"path": "system.clientmodel/1.5.1",
"hashPath": "system.clientmodel.1.5.1.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/7.7.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==",
"path": "system.identitymodel.tokens.jwt/7.7.1",
"hashPath": "system.identitymodel.tokens.jwt.7.7.1.nupkg.sha512"
},
"System.IO.Ports/9.0.10": {
"type": "package",
"serviceable": true,
"sha512": "sha512-jMvwu+NOk/+vlOzTp9vpxIeGq+yRA+3EbkmpLMs37AAy9cI8YlY/ntTHL00w26Tvu6cIkx0/TdjmeHm0l99Nqw==",
"path": "system.io.ports/9.0.10",
"hashPath": "system.io.ports.9.0.10.nupkg.sha512"
},
"System.Memory.Data/8.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BVYuec3jV23EMRDeR7Dr1/qhx7369dZzJ9IWy2xylvb4YfXsrUxspWc4UWYid/tj4zZK58uGZqn2WQiaDMhmAg==",
"path": "system.memory.data/8.0.1",
"hashPath": "system.memory.data.8.0.1.nupkg.sha512"
}
}
}

BIN
bin/Debug/net9.0-windows/Housing.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Housing.exe

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Housing.pdb

Binary file not shown.

19
bin/Debug/net9.0-windows/Housing.runtimeconfig.json

@ -0,0 +1,19 @@
{
"runtimeOptions": {
"tfm": "net9.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "9.0.0"
},
{
"name": "Microsoft.WindowsDesktop.App",
"version": "9.0.0"
}
],
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false,
"CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false
}
}
}

5
bin/Debug/net9.0-windows/InspectionSettings.ini

@ -0,0 +1,5 @@
[Judgement]
VMin=0.00
VMax=9.99
AMin=0.00
AMax=9.99

BIN
bin/Debug/net9.0-windows/Microsoft.Bcl.AsyncInterfaces.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Bcl.Cryptography.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Data.SqlClient.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Extensions.Caching.Abstractions.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Extensions.Caching.Memory.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Extensions.DependencyInjection.Abstractions.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Extensions.Logging.Abstractions.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Extensions.Options.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Extensions.Primitives.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Identity.Client.Extensions.Msal.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.Identity.Client.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.IdentityModel.Abstractions.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.IdentityModel.JsonWebTokens.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.IdentityModel.Logging.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.IdentityModel.Protocols.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.IdentityModel.Tokens.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/Microsoft.SqlServer.Server.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/System.ClientModel.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/System.IO.Ports.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/System.IdentityModel.Tokens.Jwt.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/System.Memory.Data.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/cs/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/de/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/es/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/fr/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/it/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/ja/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/ko/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/pl/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/pt-BR/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

BIN
bin/Debug/net9.0-windows/ru/Microsoft.Data.SqlClient.resources.dll

Binary file not shown.

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save