"Replace OWIN self-hosting with WebView2 virtual hosting" -m "-

Remove OWIN server implementation (StaticFileServer, Startup)" -m "- Implement
    WebView2 SetVirtualHostNameToFolderMapping in Frm_WebManual" -m "- Remove all
   OWIN NuGet packages from packages.config and .vbproj" -m "- Add comprehensive
   guide document (WEBVIEW2_VIRTUAL_HOSTING.md)" -m "- Mark legacy OWIN files as
   deprecated
This commit is contained in:
2025-12-01 20:55:42 +09:00
parent 1d6c51df3b
commit 132ddc6495
12 changed files with 155 additions and 1057 deletions

View File

@@ -113,26 +113,6 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\Interop.VBIDE.dll</HintPath> <HintPath>..\Interop.VBIDE.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\lib\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.FileSystems, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\lib\Microsoft.Owin.FileSystems.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Host.HttpListener, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\lib\Microsoft.Owin.Host.HttpListener.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\lib\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.StaticFiles, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\lib\Microsoft.Owin.StaticFiles.dll</HintPath>
</Reference>
<Reference Include="Microsoft.ReportViewer.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <Reference Include="Microsoft.ReportViewer.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<Reference Include="Microsoft.ReportViewer.WinForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> <Reference Include="Microsoft.ReportViewer.WinForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Web.WebView2.Core, Version=1.0.3537.50, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL"> <Reference Include="Microsoft.Web.WebView2.Core, Version=1.0.3537.50, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
@@ -144,10 +124,6 @@
<Reference Include="Microsoft.Web.WebView2.Wpf, Version=1.0.3537.50, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL"> <Reference Include="Microsoft.Web.WebView2.Wpf, Version=1.0.3537.50, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.3537.50\lib\net462\Microsoft.Web.WebView2.Wpf.dll</HintPath> <HintPath>..\packages\Microsoft.Web.WebView2.1.0.3537.50\lib\net462\Microsoft.Web.WebView2.Wpf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\lib\Owin.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
@@ -524,9 +500,6 @@
<Compile Include="Forms_Basic\Frm_FileInfo.vb"> <Compile Include="Forms_Basic\Frm_FileInfo.vb">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="WebServer\Example_WebServer_Usage.vb" />
<Compile Include="WebServer\Startup.vb" />
<Compile Include="WebServer\StaticFileServer.vb" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Forms_Basic\Frm_DisplayGubun.resx"> <EmbeddedResource Include="Forms_Basic\Frm_DisplayGubun.resx">
@@ -837,7 +810,6 @@
<Content Include="icon5.ico" /> <Content Include="icon5.ico" />
<None Include="Resources\select_by_difference.png" /> <None Include="Resources\select_by_difference.png" />
<None Include="Resources\page_copy.png" /> <None Include="Resources\page_copy.png" />
<Content Include="WebServer\INSTALL.txt" />
<Content Include="단축키.txt"> <Content Include="단축키.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@@ -856,7 +828,6 @@
<Content Include="Forms_Input\ReadMe.txt"> <Content Include="Forms_Input\ReadMe.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<None Include="WebServer\README.md" />
<None Include="방위2.png" /> <None Include="방위2.png" />
<None Include="방위.png" /> <None Include="방위.png" />
<None Include="방위.jpg" /> <None Include="방위.jpg" />

View File

@@ -4,27 +4,50 @@ Imports Microsoft.Web.WebView2.Core
Public Class Frm_WebManual Public Class Frm_WebManual
Public Sub Navigate(url As String)
Try
If WebView21 IsNot Nothing AndAlso WebView21.CoreWebView2 IsNot Nothing Then
WebView21.CoreWebView2.Navigate(url)
End If
Catch ex As Exception
MessageBox.Show("웹페이지 이동 중 오류가 발생했습니다: " & ex.Message,
"오류", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Private Async Sub Frm_WebManual_Load(sender As Object, e As EventArgs) Handles MyBase.Load Private Async Sub Frm_WebManual_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try Try
' WebView2 초기화 (Runtime이 없으면 자동 다운로드) ' WebView2 초기화
Await InitializeWebView2Async() Await InitializeWebView2Async()
' 로컬 웹서버 페이지 로드
If WebView21.CoreWebView2 IsNot Nothing Then
WebView21.CoreWebView2.Navigate("http://localhost:58123/") Try
End If
' 가상 호스팅 설정
If WebView21.CoreWebView2 Is Nothing Then
Return
End If
' wwwroot 경로 확인
Dim _wwwrootPath As String = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot")
If String.IsNullOrEmpty(_wwwrootPath) Then
_wwwrootPath = Path.Combine(Application.StartupPath, "wwwroot")
End If
' 디렉토리가 없으면 생성
If Not Directory.Exists(_wwwrootPath) Then
Directory.CreateDirectory(_wwwrootPath)
End If
' 가상 호스트 매핑 설정
' https://eco2.local/ -> 로컬 폴더 매핑
WebView21.CoreWebView2.SetVirtualHostNameToFolderMapping(
"eco2.local",
_wwwrootPath,
CoreWebView2HostResourceAccessKind.Allow)
If WebView21 IsNot Nothing AndAlso WebView21.CoreWebView2 IsNot Nothing Then
' 가상 호스트 URL 사용
Dim url As String = "https://eco2.local/index.html"
WebView21.CoreWebView2.Navigate(url)
End If
Catch ex As Exception
MessageBox.Show("웹페이지 이동 중 오류가 발생했습니다: " & ex.Message,
"오류", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Catch ex As Exception Catch ex As Exception
MessageBox.Show("웹페이지 로드 중 오류가 발생했습니다: " & ex.Message, MessageBox.Show("웹페이지 로드 중 오류가 발생했습니다: " & ex.Message,
@@ -62,4 +85,5 @@ Public Class Frm_WebManual
End Try End Try
End Function End Function
End Class End Class

View File

@@ -91,6 +91,7 @@ Partial Class MdiMain
Me.CloseAllToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem() Me.CloseAllToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
Me.ArrangeIconsToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem() Me.ArrangeIconsToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
Me.btcustomprofile = New System.Windows.Forms.ToolStripMenuItem() Me.btcustomprofile = New System.Windows.Forms.ToolStripMenuItem()
Me.ManualToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
Me.TreeView1 = New System.Windows.Forms.TreeView() Me.TreeView1 = New System.Windows.Forms.TreeView()
Me.ContextMenuStrip1 = New System.Windows.Forms.ContextMenuStrip(Me.components) Me.ContextMenuStrip1 = New System.Windows.Forms.ContextMenuStrip(Me.components)
Me.그룹추가ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem() Me.그룹추가ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
@@ -109,7 +110,6 @@ Partial Class MdiMain
Me.비교데이터백업ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem() Me.비교데이터백업ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
Me.데이터비교ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem() Me.데이터비교ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
Me.순실체적ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem() Me.순실체적ToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
Me.ManualToolStripMenuItem = New System.Windows.Forms.ToolStripMenuItem()
Me.StatusStrip1.SuspendLayout() Me.StatusStrip1.SuspendLayout()
Me.MenuStrip1.SuspendLayout() Me.MenuStrip1.SuspendLayout()
Me.ContextMenuStrip1.SuspendLayout() Me.ContextMenuStrip1.SuspendLayout()
@@ -555,6 +555,13 @@ Partial Class MdiMain
Me.btcustomprofile.Text = "커스텀프로필" Me.btcustomprofile.Text = "커스텀프로필"
Me.btcustomprofile.Visible = False Me.btcustomprofile.Visible = False
' '
'ManualToolStripMenuItem
'
Me.ManualToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right
Me.ManualToolStripMenuItem.Name = "ManualToolStripMenuItem"
Me.ManualToolStripMenuItem.Size = New System.Drawing.Size(59, 20)
Me.ManualToolStripMenuItem.Text = "Manual"
'
'TreeView1 'TreeView1
' '
Me.TreeView1.ContextMenuStrip = Me.ContextMenuStrip1 Me.TreeView1.ContextMenuStrip = Me.ContextMenuStrip1
@@ -697,13 +704,6 @@ Partial Class MdiMain
Me.순실체적ToolStripMenuItem.Size = New System.Drawing.Size(170, 22) Me.순실체적ToolStripMenuItem.Size = New System.Drawing.Size(170, 22)
Me.순실체적ToolStripMenuItem.Text = "3.순실체적" Me.순실체적ToolStripMenuItem.Text = "3.순실체적"
' '
'ManualToolStripMenuItem
'
Me.ManualToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right
Me.ManualToolStripMenuItem.Name = "ManualToolStripMenuItem"
Me.ManualToolStripMenuItem.Size = New System.Drawing.Size(59, 20)
Me.ManualToolStripMenuItem.Text = "Manual"
'
'MdiMain 'MdiMain
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(7.0!, 12.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(7.0!, 12.0!)

View File

@@ -127,6 +127,31 @@
<value>235, 17</value> <value>235, 17</value>
</metadata> </metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="bt_filesave.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
R0lGODlhEAAQAIQAAJXD9Iasxm6MqnSn2lZtjVaRyEpXbYu767TX/2KZztvr/4Gy5KrT/3ut32+gzlFh
e+r0/0RNX9/u/9Ln+8Xg//n8/4e36CkxQz9GVkSCvKjL35/N/Je91K7T5bDS4////yH/C05FVFNDQVBF
Mi4wAwEBAAAh+QQAAAAAACwAAAAAEAAQAAAIuQA/CBxIsKDACRwScggQwIGAhwIICBDYQcEEgwg+bNjw
QKCHCQgkQBgpQcKBCg0AEBCoAaRIkhIsVBigUiAHCgwkKNjJU8GAAx0/3NwIAMABCwsaDHCwIGgAChuK
HjiQdMDSAQYEPpWKtKqDBA6yfgiAwGhXpUsTJIgg0AGCo0nRfi1QgO0HAQyQNpCrtkAGDAIFbKi69GsC
un8FEohqdEFavxkyXAhMoPKDBwYMRIiAAcOFoAZDCwwIADs=
</value>
</data>
<data name="bt_데이터관리.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m
dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIcSURBVDhPjVPJqhpBFO1VFvmAt0g+Iav3E9nlM7LM
ZyS7rLoc2wFbbGi7bRBxJYojIk6o+BTFCQVHTKsIL1HfDaeIIv0IScGB4tY9Q93qFohIsCKbzX6LxWIz
WZZfAOxRs/YBrwqRSORBVdVfZFmoKYryztp/7ziSZfkiyzJFo1F6enqiy+VC5/OZWq0Wr+EMPei9JuIC
qqo+37uNx2PSdZ0ajQaHpmm8dr/+cATBMAy/YRjUbre5I1AsFikej1MwGOTAHjWkOZ1O1Gw2CRyv16sI
uq6fut0uVatVqtVq3BHu1nVNVKlUKJPJUCqVIkmSToKmaebhcKDlckmDwYCGwyFls1nq9Xq3RNjncjnq
dDqUSCQ46vU6ud1uUwiHw1xgt9vRdrulyWTC45bL5dsM4IohgphOpzmQ1uVymRggFzBNkzabDa1WK5rN
ZtwVV8vn85yIyEiGJBCAgdPpNAVFUX4ej0fa7/c0n885eTQaUb/f50+JZhCvSCaTXKxUKpHNZnsWQqFQ
AoXpdMqvARHMAgkggDMMDUASOENUURRijGWEYDD4Rpblz4FAoI+mxWJB6/WaDxMC16GBiNngm2CMjRlj
X0RRfHv7JP1+/4PP5/vq9Xp/FAoFLgIxDBBPHIvFEPnAGPsuiuL7v/4LHo/ngyRJIbfb/QIi7hwIBEDW
GWOP1v5XAlc4nc6PDocjZbfb8zab7ZP1/J8C/4vfXG8tHKjVxdQAAAAASUVORK5CYII=
</value>
</data>
<data name="ReportToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ReportToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
R0lGODlhEAAQAIQfAOvGUf7ztuvPMf/78/fkl/Pbg+u8Rvjqteu2Pf3zxPz36Pz0z+vTmPzurPvuw/np R0lGODlhEAAQAIQfAOvGUf7ztuvPMf/78/fkl/Pbg+u8Rvjqteu2Pf3zxPz36Pz0z+vTmPzurPvuw/np
@@ -223,31 +248,6 @@
b6AQ75sCVnsVfDHIceuzCVkfYyw4KQ2Mqa8QnWkVq15THp6eXNzdMla0d1nuyiIoVKNTHJMGrFWX2Jhu b6AQ75sCVnsVfDHIceuzCVkfYyw4KQ2Mqa8QnWkVq15THp6eXNzdMla0d1nuyiIoVKNTHJMGrFWX2Jhu
IjLRwPp4HeGRGrEaFNQEhh/it1TSde9IOmC327HZbAyVX+Bd6TnxUKYHZ+hVnsKQfwL9/eNoc4/SKT9M IjLRwPp4HeGRGrEaFNQEhh/it1TSde9IOmC327HZbAyVX+Bd6TnxUKYHZ+hVnsKQfwL9/eNoc4/SKT9M
h+wQKpVKnLQN/mV+AQV66PCS6TFTAAAAAElFTkSuQmCC h+wQKpVKnLQN/mV+AQV66PCS6TFTAAAAAElFTkSuQmCC
</value>
</data>
<data name="bt_filesave.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
R0lGODlhEAAQAIQAAJXD9Iasxm6MqnSn2lZtjVaRyEpXbYu767TX/2KZztvr/4Gy5KrT/3ut32+gzlFh
e+r0/0RNX9/u/9Ln+8Xg//n8/4e36CkxQz9GVkSCvKjL35/N/Je91K7T5bDS4////yH/C05FVFNDQVBF
Mi4wAwEBAAAh+QQAAAAAACwAAAAAEAAQAAAIuQA/CBxIsKDACRwScggQwIGAhwIICBDYQcEEgwg+bNjw
QKCHCQgkQBgpQcKBCg0AEBCoAaRIkhIsVBigUiAHCgwkKNjJU8GAAx0/3NwIAMABCwsaDHCwIGgAChuK
HjiQdMDSAQYEPpWKtKqDBA6yfgiAwGhXpUsTJIgg0AGCo0nRfi1QgO0HAQyQNpCrtkAGDAIFbKi69GsC
un8FEohqdEFavxkyXAhMoPKDBwYMRIiAAcOFoAZDCwwIADs=
</value>
</data>
<data name="bt_데이터관리.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m
dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIcSURBVDhPjVPJqhpBFO1VFvmAt0g+Iav3E9nlM7LM
ZyS7rLoc2wFbbGi7bRBxJYojIk6o+BTFCQVHTKsIL1HfDaeIIv0IScGB4tY9Q93qFohIsCKbzX6LxWIz
WZZfAOxRs/YBrwqRSORBVdVfZFmoKYryztp/7ziSZfkiyzJFo1F6enqiy+VC5/OZWq0Wr+EMPei9JuIC
qqo+37uNx2PSdZ0ajQaHpmm8dr/+cATBMAy/YRjUbre5I1AsFikej1MwGOTAHjWkOZ1O1Gw2CRyv16sI
uq6fut0uVatVqtVq3BHu1nVNVKlUKJPJUCqVIkmSToKmaebhcKDlckmDwYCGwyFls1nq9Xq3RNjncjnq
dDqUSCQ46vU6ud1uUwiHw1xgt9vRdrulyWTC45bL5dsM4IohgphOpzmQ1uVymRggFzBNkzabDa1WK5rN
ZtwVV8vn85yIyEiGJBCAgdPpNAVFUX4ej0fa7/c0n885eTQaUb/f50+JZhCvSCaTXKxUKpHNZnsWQqFQ
AoXpdMqvARHMAgkggDMMDUASOENUURRijGWEYDD4Rpblz4FAoI+mxWJB6/WaDxMC16GBiNngm2CMjRlj
X0RRfHv7JP1+/4PP5/vq9Xp/FAoFLgIxDBBPHIvFEPnAGPsuiuL7v/4LHo/ngyRJIbfb/QIi7hwIBEDW
GWOP1v5XAlc4nc6PDocjZbfb8zab7ZP1/J8C/4vfXG8tHKjVxdQAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<metadata name="ContextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="ContextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -331,72 +331,72 @@
<value> <value>
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
k1iG/rMj4QAAAABJRU5ErkJggg== 2FiAVmb3aQAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ToolStripButton3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ToolStripButton3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

View File

@@ -1,5 +1,4 @@
Imports System.IO Imports System.IO
Imports Eco2Ar.WebServer
Public Class MdiMain Public Class MdiMain
@@ -21,17 +20,9 @@ Public Class MdiMain
'''현재열려있는폼의 이름을 변경한다. '''현재열려있는폼의 이름을 변경한다.
Public OpenedForm As E_MenuIdx = E_MenuIdx.NONE Public OpenedForm As E_MenuIdx = E_MenuIdx.NONE
Private webServer As StaticFileServer
Private Sub MdiMain_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed Private Sub MdiMain_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
pLog.Add("FormClosed", True) pLog.Add("FormClosed", True)
' 웹 서버 정리
If webServer IsNot Nothing Then
webServer.Stop()
webServer.Dispose()
End If
End Sub End Sub
Private Sub MdiMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing Private Sub MdiMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
@@ -252,19 +243,6 @@ Public Class MdiMain
pLog.Add("Program Start") pLog.Add("Program Start")
Try
' 웹 서버 초기화 및 시작
Dim wwwPath = Path.Combine(Application.StartupPath, "wwwroot")
webServer = New StaticFileServer(wwwPath, 58123)
webServer.Start()
'If System.Diagnostics.Debugger.IsAttached Then
' webServer.OpenInBrowser()
'End If
Catch ex As Exception
' 웹 서버 시작 실패해도 프로그램은 계속 실행
Debug.WriteLine("웹 서버 시작 실패: " & ex.Message)
End Try
' WebView2 Fixed Version 체크 ' WebView2 Fixed Version 체크
CheckWebView2Runtime() CheckWebView2Runtime()
@@ -3991,14 +3969,22 @@ ENDSTAT: '//오류발생시 강제종료를 위한 분기문
Dim frmManual As Frm_WebManual = Nothing Dim frmManual As Frm_WebManual = Nothing
Private Sub ManualToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ManualToolStripMenuItem.Click Private Sub ManualToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ManualToolStripMenuItem.Click
If frmManual Is Nothing OrElse frmManual.IsDisposed Then Try
frmManual = New Frm_WebManual() If frmManual Is Nothing OrElse frmManual.IsDisposed Then
frmManual = New Frm_WebManual()
End If
If frmManual.WindowState = FormWindowState.Minimized Then
frmManual.WindowState = FormWindowState.Normal
End If
frmManual.Show() frmManual.Show()
End If frmManual.Activate()
If frmManual.WindowState = FormWindowState.Minimized Then Catch ex As Exception
frmManual.WindowState = FormWindowState.Normal MessageBox.Show("매뉴얼 표시 중 오류가 발생했습니다: " & ex.Message,
End If "오류", MessageBoxButtons.OK, MessageBoxIcon.Error)
frmManual.Activate() End Try
End Sub End Sub
''' <summary> ''' <summary>

View File

@@ -1,244 +0,0 @@
' OWIN 정적 파일 호스팅 서버 사용 예제
'
' 이 파일은 StaticFileServer를 사용하는 방법을 보여줍니다.
' 실제 사용 시에는 MdiMain.vb 또는 필요한 폼에서 사용하세요.
Imports Eco2Ar.WebServer
Imports System.IO
Namespace Examples
''' <summary>
''' 웹 서버 사용 예제
''' </summary>
Public Class WebServerExample
Private server As StaticFileServer
''' <summary>
''' 예제 1: 기본 사용법
''' </summary>
Public Sub Example1_BasicUsage()
' 1. 정적 파일을 서빙할 디렉토리 경로 설정
Dim wwwrootPath As String = Path.Combine(Application.StartupPath, "wwwroot")
' 2. 서버 인스턴스 생성 (포트 58123 사용)
server = New StaticFileServer(wwwrootPath, 58123)
' 3. 서버 시작
server.Start()
' 4. 브라우저에서 열기 (선택사항)
' server.OpenInBrowser()
MsgBox("웹 서버가 시작되었습니다." & vbCrLf & _
"URL: " & server.BaseUrl & vbCrLf & _
"루트 경로: " & server.RootPath, _
MsgBoxStyle.Information, "웹 서버")
End Sub
''' <summary>
''' 예제 2: MdiMain에서 사용 (프로그램 시작 시 서버 시작)
''' </summary>
Public Sub Example2_IntegrationWithMdiMain()
' MdiMain.vb의 MdiMain_Load 이벤트에 추가:
'
' Private webServer As StaticFileServer
'
' Private Sub MdiMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' ' ... 기존 코드 ...
'
' Try
' ' 웹 서버 초기화 및 시작
' Dim wwwPath = Path.Combine(Application.StartupPath, "wwwroot")
' webServer = New StaticFileServer(wwwPath)
' webServer.Start()
' Catch ex As Exception
' ' 웹 서버 시작 실패해도 프로그램은 계속 실행
' Debug.WriteLine("웹 서버 시작 실패: " & ex.Message)
' End Try
' End Sub
'
' Private Sub MdiMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
' ' ... 기존 코드 ...
'
' ' 웹 서버 정리
' If webServer IsNot Nothing Then
' webServer.Stop()
' webServer.Dispose()
' End If
' End Sub
End Sub
''' <summary>
''' 예제 3: 특정 파일 브라우저에서 열기
''' </summary>
Public Sub Example3_OpenSpecificFile()
If server Is Nothing OrElse Not server.IsRunning Then
MsgBox("서버가 실행 중이 아닙니다.", MsgBoxStyle.Exclamation, "오류")
Return
End If
' 리포트 HTML 파일 열기
server.OpenFileInBrowser("report.html")
' 또는 URL만 가져오기
Dim reportUrl As String = server.GetFileUrl("reports/2025/report.html")
MsgBox("리포트 URL: " & reportUrl, MsgBoxStyle.Information, "URL")
End Sub
''' <summary>
''' 예제 4: 동적으로 HTML 파일 생성 후 표시
''' </summary>
Public Sub Example4_GenerateAndDisplay()
If server Is Nothing OrElse Not server.IsRunning Then
MsgBox("서버가 실행 중이 아닙니다.", MsgBoxStyle.Exclamation, "오류")
Return
End If
' HTML 파일 생성
Dim htmlContent As String = "<!DOCTYPE html>" & vbCrLf & _
"<html>" & vbCrLf & _
"<head>" & vbCrLf & _
" <meta charset=""utf-8"">" & vbCrLf & _
" <title>ECO2 리포트</title>" & vbCrLf & _
" <style>" & vbCrLf & _
" body { font-family: 'Malgun Gothic', sans-serif; margin: 20px; }" & vbCrLf & _
" h1 { color: #2c3e50; }" & vbCrLf & _
" table { border-collapse: collapse; width: 100%; }" & vbCrLf & _
" th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }" & vbCrLf & _
" th { background-color: #4CAF50; color: white; }" & vbCrLf & _
" </style>" & vbCrLf & _
"</head>" & vbCrLf & _
"<body>" & vbCrLf & _
" <h1>건물 에너지 분석 리포트</h1>" & vbCrLf & _
" <table>" & vbCrLf & _
" <tr><th>항목</th><th>값</th></tr>" & vbCrLf & _
" <tr><td>1차 에너지 소요량</td><td>123.45 kWh/m²·year</td></tr>" & vbCrLf & _
" <tr><td>CO2 배출량</td><td>45.67 kg/m²·year</td></tr>" & vbCrLf & _
" </table>" & vbCrLf & _
"</body>" & vbCrLf & _
"</html>"
' 파일 저장
Dim reportPath As String = Path.Combine(server.RootPath, "report.html")
File.WriteAllText(reportPath, htmlContent, System.Text.Encoding.UTF8)
' 브라우저에서 열기
server.OpenFileInBrowser("report.html")
End Sub
''' <summary>
''' 예제 5: 폼 버튼에서 웹 리포트 생성 및 표시
''' </summary>
Public Sub Example5_ButtonClick()
' 폼의 버튼 클릭 이벤트에 추가:
'
' Private Sub btnShowWebReport_Click(sender As Object, e As EventArgs) Handles btnShowWebReport.Click
' Try
' ' 서버가 실행 중이 아니면 시작
' If webServer Is Nothing OrElse Not webServer.IsRunning Then
' Dim wwwPath = Path.Combine(Application.StartupPath, "wwwroot")
' webServer = New StaticFileServer(wwwPath)
' webServer.Start()
' End If
'
' ' HTML 리포트 생성
' GenerateHtmlReport()
'
' ' 브라우저에서 열기
' webServer.OpenFileInBrowser("report.html")
' Catch ex As Exception
' MsgBox("리포트 생성 실패: " & ex.Message, MsgBoxStyle.Critical, "오류")
' End Try
' End Sub
'
' Private Sub GenerateHtmlReport()
' ' 실제 데이터를 사용하여 HTML 생성
' Dim html As String = BuildHtmlReport(DSET1, DSETR1, Result2)
' Dim path As String = Path.Combine(webServer.RootPath, "report.html")
' File.WriteAllText(path, html, System.Text.Encoding.UTF8)
' End Sub
End Sub
''' <summary>
''' 서버 중지
''' </summary>
Public Sub StopServer()
If server IsNot Nothing Then
server.Stop()
server.Dispose()
server = Nothing
End If
End Sub
End Class
''' <summary>
''' 간단한 HTML 빌더 헬퍼 클래스
''' </summary>
Public Class HtmlReportBuilder
Private html As System.Text.StringBuilder
Public Sub New(title As String)
html = New System.Text.StringBuilder()
html.AppendLine("<!DOCTYPE html>")
html.AppendLine("<html>")
html.AppendLine("<head>")
html.AppendLine(" <meta charset=""utf-8"">")
html.AppendLine(" <title>" & title & "</title>")
html.AppendLine(" <style>")
html.AppendLine(" body { font-family: 'Malgun Gothic', sans-serif; margin: 20px; }")
html.AppendLine(" h1 { color: #2c3e50; }")
html.AppendLine(" h2 { color: #34495e; border-bottom: 2px solid #3498db; padding-bottom: 5px; }")
html.AppendLine(" table { border-collapse: collapse; width: 100%; margin: 20px 0; }")
html.AppendLine(" th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }")
html.AppendLine(" th { background-color: #4CAF50; color: white; }")
html.AppendLine(" tr:nth-child(even) { background-color: #f2f2f2; }")
html.AppendLine(" .section { margin: 30px 0; }")
html.AppendLine(" </style>")
html.AppendLine("</head>")
html.AppendLine("<body>")
html.AppendLine(" <h1>" & title & "</h1>")
End Sub
Public Sub AddSection(sectionTitle As String)
html.AppendLine(" <div class=""section"">")
html.AppendLine(" <h2>" & sectionTitle & "</h2>")
End Sub
Public Sub StartTable(ParamArray headers As String())
html.AppendLine(" <table>")
html.Append(" <tr>")
For Each headerItem As String In headers
html.Append("<th>" & headerItem & "</th>")
Next
html.AppendLine("</tr>")
End Sub
Public Sub AddRow(ParamArray cells As String())
html.Append(" <tr>")
For Each cellItem As String In cells
html.Append("<td>" & cellItem & "</td>")
Next
html.AppendLine("</tr>")
End Sub
Public Sub EndTable()
html.AppendLine(" </table>")
End Sub
Public Sub EndSection()
html.AppendLine(" </div>")
End Sub
Public Function Build() As String
html.AppendLine("</body>")
html.AppendLine("</html>")
Return html.ToString()
End Function
End Class
End Namespace

View File

@@ -1,50 +0,0 @@
=====================================================
OWIN 정적 파일 호스팅 서버 설치 가이드
=====================================================
1. Visual Studio에서 ECO2_2025V1 프로젝트 열기
2. 메뉴: 도구 > NuGet 패키지 관리자 > 패키지 관리자 콘솔
3. 다음 명령들을 순서대로 실행:
Install-Package Owin -Version 1.0
Install-Package Microsoft.Owin -Version 2.1.0
Install-Package Microsoft.Owin.Host.HttpListener -Version 2.1.0
Install-Package Microsoft.Owin.Hosting -Version 2.1.0
Install-Package Microsoft.Owin.StaticFiles -Version 2.1.0
4. 프로젝트 다시 빌드
5. wwwroot 폴더 생성 (없는 경우):
- 출력 디렉토리에 wwwroot 폴더 생성
- Debug: ..\..\..\..\..\eco2\debug_2016\wwwroot
- Release: c:\eco2\debug_2016\wwwroot
6. 기본 index.html 생성 (선택사항):
wwwroot\index.html 파일에 다음 내용 추가:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECO2 Web Server</title>
</head>
<body>
<h1>ECO2 웹 서버가 정상 작동 중입니다</h1>
</body>
</html>
7. 사용 예제는 Example_WebServer_Usage.vb 참고
8. 관리자 권한 필요 시 (선택사항):
관리자 권한 명령 프롬프트에서:
netsh http add urlacl url=http://+:58123/ user=Everyone
=====================================================
문제 발생 시:
- README.md의 "문제 해결" 섹션 참고
- 패키지 버전이 정확한지 확인 (2.1.0)
- .NET Framework 4.0 타겟이 맞는지 확인
=====================================================

View File

@@ -1,126 +0,0 @@
# Visual Studio 2010 수동 설치 가이드
VS2010에는 NuGet이 기본 내장되어 있지 않으므로, 두 가지 방법 중 선택할 수 있습니다.
## 방법 1: NuGet Extension 설치 (권장)
1. Visual Studio 2010 열기
2. **도구** > **확장 관리자** 클릭
3. **온라인 갤러리** 선택
4. 검색창에 "NuGet Package Manager" 입력
5. **NuGet Package Manager** 찾아서 **다운로드** 클릭
6. 설치 후 Visual Studio 재시작
7. 이후 README.md의 NuGet 설치 방법 따라하기
또는 직접 다운로드:
https://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c
## 방법 2: DLL 수동 추가 (NuGet 없이)
### 1단계: 필요한 DLL 다운로드
다음 NuGet 패키지를 직접 다운로드:
**다운로드 링크:**
- https://www.nuget.org/packages/Owin/1.0
- https://www.nuget.org/packages/Microsoft.Owin/2.1.0
- https://www.nuget.org/packages/Microsoft.Owin.Host.HttpListener/2.1.0
- https://www.nuget.org/packages/Microsoft.Owin.Hosting/2.1.0
- https://www.nuget.org/packages/Microsoft.Owin.StaticFiles/2.1.0
- https://www.nuget.org/packages/Microsoft.Owin.FileSystems/2.1.0
각 페이지에서 "Download package" 클릭
### 2단계: NuGet 패키지에서 DLL 추출
1. 다운로드한 `.nupkg` 파일의 확장자를 `.zip`으로 변경
2. 압축 해제
3. `lib\net40\` 폴더에서 DLL 파일 찾기
4. 프로젝트 폴더에 `lib` 디렉토리 생성
5. 모든 DLL을 `S:\Source\KICT\ECO2\lib\` 폴더에 복사
**필요한 DLL 목록:**
- Owin.dll
- Microsoft.Owin.dll
- Microsoft.Owin.Host.HttpListener.dll
- Microsoft.Owin.Hosting.dll
- Microsoft.Owin.StaticFiles.dll
- Microsoft.Owin.FileSystems.dll
### 3단계: Visual Studio 프로젝트에 참조 추가
1. 솔루션 탐색기에서 **ECO2_2025V1** 프로젝트 선택
2. **참조** 폴더 우클릭 > **참조 추가**
3. **찾아보기** 탭 선택
4. `S:\Source\KICT\ECO2\lib\` 폴더로 이동
5. 위의 모든 DLL 선택하여 추가
### 4단계: app.config에 바인딩 리디렉션 추가
`ArinWarev1\app.config` 파일을 열고 `</configuration>` 바로 앞에 추가:
```xml
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
```
## 방법 3: 스크립트로 자동 다운로드 (PowerShell)
프로젝트 루트에서 PowerShell 실행:
```powershell
# lib 폴더 생성
New-Item -ItemType Directory -Force -Path "lib"
# NuGet.exe 다운로드
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/v2.8.6/nuget.exe" -OutFile "nuget.exe"
# 패키지 다운로드
.\nuget.exe install Owin -Version 1.0 -OutputDirectory packages
.\nuget.exe install Microsoft.Owin -Version 2.1.0 -OutputDirectory packages
.\nuget.exe install Microsoft.Owin.Host.HttpListener -Version 2.1.0 -OutputDirectory packages
.\nuget.exe install Microsoft.Owin.Hosting -Version 2.1.0 -OutputDirectory packages
.\nuget.exe install Microsoft.Owin.StaticFiles -Version 2.1.0 -OutputDirectory packages
# DLL 복사
Copy-Item "packages\Owin.1.0\lib\net40\Owin.dll" -Destination "lib\"
Copy-Item "packages\Microsoft.Owin.2.1.0\lib\net40\Microsoft.Owin.dll" -Destination "lib\"
Copy-Item "packages\Microsoft.Owin.Host.HttpListener.2.1.0\lib\net40\Microsoft.Owin.Host.HttpListener.dll" -Destination "lib\"
Copy-Item "packages\Microsoft.Owin.Hosting.2.1.0\lib\net40\Microsoft.Owin.Hosting.dll" -Destination "lib\"
Copy-Item "packages\Microsoft.Owin.StaticFiles.2.1.0\lib\net40\Microsoft.Owin.StaticFiles.dll" -Destination "lib\"
Copy-Item "packages\Microsoft.Owin.FileSystems.2.1.0\lib\net40\Microsoft.Owin.FileSystems.dll" -Destination "lib\"
Write-Host "DLL 다운로드 완료! lib 폴더를 확인하세요."
```
## 방법 4: 미리 준비된 DLL 사용
팀원에게 이미 설치된 환경에서 다음 폴더의 DLL을 복사 받기:
- `packages\Owin.1.0\lib\net40\`
- `packages\Microsoft.Owin.2.1.0\lib\net40\`
- `packages\Microsoft.Owin.Host.HttpListener.2.1.0\lib\net40\`
- `packages\Microsoft.Owin.Hosting.2.1.0\lib\net40\`
- `packages\Microsoft.Owin.StaticFiles.2.1.0\lib\net40\`
- `packages\Microsoft.Owin.FileSystems.2.1.0\lib\net40\`
## 확인 방법
프로젝트를 빌드했을 때 다음 오류가 없으면 성공:
- "형식 또는 네임스페이스 이름 'Owin'을 찾을 수 없습니다"
- "형식 또는 네임스페이스 이름 'Microsoft'을 찾을 수 없습니다"
## 문제 해결
### "Could not load file or assembly" 오류
- app.config에 바인딩 리디렉션 추가했는지 확인
- DLL 버전이 2.1.0이 맞는지 확인 (2.x 버전만 .NET 4.0 호환)
### "파일을 찾을 수 없습니다" 오류
- 출력 디렉토리에 DLL이 복사되는지 확인
- 참조의 "로컬 복사" 속성이 True인지 확인

View File

@@ -1,190 +0,0 @@
# OWIN 정적 파일 호스팅 서버
ECO2 프로젝트에 OWIN 기반 내장 웹 서버를 추가하여 HTML 리포트 및 정적 파일을 호스팅할 수 있습니다.
## 설치 방법
### 1. NuGet 패키지 설치
Visual Studio에서 Package Manager Console을 열고 다음 명령을 실행하세요:
```powershell
# ECO2_2025V1 프로젝트를 기본 프로젝트로 선택 후 실행
Install-Package Microsoft.Owin -Version 2.1.0
Install-Package Microsoft.Owin.Host.HttpListener -Version 2.1.0
Install-Package Microsoft.Owin.Hosting -Version 2.1.0
Install-Package Microsoft.Owin.StaticFiles -Version 2.1.0
Install-Package Owin -Version 1.0
```
또는 패키지 관리자 UI에서 다음 패키지를 검색하여 설치:
- Microsoft.Owin (2.1.0)
- Microsoft.Owin.Host.HttpListener (2.1.0)
- Microsoft.Owin.Hosting (2.1.0)
- Microsoft.Owin.StaticFiles (2.1.0)
- Owin (1.0)
### 2. 프로젝트에 파일 추가
다음 파일들이 `WebServer` 폴더에 추가되었습니다:
- `StaticFileServer.vb` - 메인 서버 클래스
- `Startup.vb` - OWIN 시작 구성
- `Example_WebServer_Usage.vb` - 사용 예제
Visual Studio에서 프로젝트를 다시 로드하면 자동으로 인식됩니다.
## 사용 방법
### 기본 사용법
```vb
Imports Eco2Ar.WebServer
Imports System.IO
' 1. 서버 인스턴스 생성
Dim wwwrootPath As String = Path.Combine(Application.StartupPath, "wwwroot")
Dim server As New StaticFileServer(wwwrootPath, 58123)
' 2. 서버 시작
server.Start()
' 3. 브라우저에서 열기
server.OpenInBrowser()
' 4. 사용 후 서버 중지
server.Stop()
```
### MdiMain에 통합
`MdiMain.vb`에 다음 코드를 추가:
```vb
Public Class MdiMain
Private webServer As StaticFileServer
Private Sub MdiMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' ... 기존 코드 ...
' 웹 서버 시작
Try
Dim wwwPath = Path.Combine(Application.StartupPath, "wwwroot")
webServer = New StaticFileServer(wwwPath)
webServer.Start()
Catch ex As Exception
Debug.WriteLine("웹 서버 시작 실패: " & ex.Message)
End Try
End Sub
Private Sub MdiMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
' ... 기존 코드 ...
' 웹 서버 정리
If webServer IsNot Nothing Then
webServer.Stop()
webServer.Dispose()
End If
End Sub
End Class
```
### HTML 리포트 생성 및 표시
```vb
' HTML 리포트 빌더 사용
Dim builder As New HtmlReportBuilder("건물 에너지 분석 리포트")
builder.AddSection("1차 에너지 소요량")
builder.StartTable("항목", "", "단위")
builder.AddRow("난방", "123.45", "kWh/m²·year")
builder.AddRow("냉방", "67.89", "kWh/m²·year")
builder.EndTable()
builder.EndSection()
Dim html As String = builder.Build()
' 파일 저장
Dim reportPath As String = Path.Combine(webServer.RootPath, "report.html")
File.WriteAllText(reportPath, html, System.Text.Encoding.UTF8)
' 브라우저에서 열기
webServer.OpenFileInBrowser("report.html")
```
## 폴더 구조
```
C:\eco2\debug_2016\
├─ Eco2Ar.exe
└─ wwwroot\ # 정적 파일 루트 디렉토리
├─ index.html # 기본 페이지
├─ report.html # 생성된 리포트
├─ css\
│ └─ styles.css
├─ js\
│ └─ scripts.js
└─ images\
└─ logo.png
```
## 주요 기능
### StaticFileServer 클래스
- **Start()** - 웹 서버 시작
- **Stop()** - 웹 서버 중지
- **OpenInBrowser()** - 기본 브라우저에서 루트 URL 열기
- **OpenFileInBrowser(relativePath)** - 특정 파일을 브라우저에서 열기
- **GetFileUrl(relativePath)** - 파일의 전체 URL 반환
- **IsRunning** - 서버 실행 상태 확인
- **BaseUrl** - 서버 URL (http://localhost:58123)
- **RootPath** - 정적 파일 루트 경로
### HtmlReportBuilder 클래스
간단한 HTML 리포트를 코드로 생성할 수 있는 헬퍼 클래스입니다.
## 포트 정보
- **기본 포트**: 58123 (일반적으로 사용하지 않는 포트)
- 필요 시 생성자에서 다른 포트 지정 가능: `New StaticFileServer(path, 9999)`
## 보안 주의사항
- 이 웹 서버는 **localhost**에서만 접근 가능합니다 (외부 접근 불가)
- 민감한 정보를 wwwroot에 저장하지 마세요
- 필요한 경우에만 서버를 실행하고 사용 후 중지하세요
## 문제 해결
### "포트가 이미 사용 중입니다" 오류
다른 프로그램이 58123 포트를 사용 중일 수 있습니다. 다른 포트를 사용하세요:
```vb
Dim server As New StaticFileServer(wwwrootPath, 58124)
```
### "관리자 권한이 필요합니다" 오류
일부 환경에서는 HTTP.sys 리스너 등록에 관리자 권한이 필요할 수 있습니다.
다음 명령을 관리자 권한 명령 프롬프트에서 실행:
```cmd
netsh http add urlacl url=http://+:58123/ user=Everyone
```
### 패키지 설치 오류
.NET Framework 4.0 타겟 프로젝트이므로 반드시 2.x 버전의 OWIN 패키지를 사용해야 합니다.
최신 버전(4.x)은 .NET Framework 4.5 이상이 필요합니다.
## 예제 코드 위치
더 자세한 사용 예제는 `Example_WebServer_Usage.vb` 파일을 참고하세요.
## 참고 자료
- [OWIN 공식 문서](http://owin.org/)
- [Microsoft.Owin 문서](https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/)

View File

@@ -1,93 +0,0 @@
' OWIN Startup 클래스
Imports Owin
Imports Microsoft.Owin.StaticFiles
Imports Microsoft.Owin.FileSystems
Namespace WebServer
''' <summary>
''' OWIN 시작 구성 클래스
''' </summary>
Public Class Startup
' 정적 필드로 RootPath 저장
Public Shared RootPath As String = String.Empty
''' <summary>
''' OWIN 미들웨어 구성
''' </summary>
''' <param name="app">App builder</param>
Public Sub Configuration(app As IAppBuilder)
' 루트 경로 확인
If String.IsNullOrEmpty(RootPath) Then
RootPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot")
End If
' 정적 파일 서빙을 위한 파일 시스템 설정
Dim fileSystem = New PhysicalFileSystem(RootPath)
' 정적 파일 옵션 설정
Dim options As New FileServerOptions() With {
.RequestPath = New Microsoft.Owin.PathString(""),
.FileSystem = fileSystem,
.EnableDirectoryBrowsing = False
}
' MIME 타입 매핑 추가 (필요한 경우)
options.StaticFileOptions.ContentTypeProvider = New CustomContentTypeProvider()
' 정적 파일 미들웨어 사용
app.UseFileServer(options)
' 기본 핸들러 (루트 경로 접근 시)
app.Run(Function(context)
' 루트 경로 접근 시 index.html로 리다이렉트
If context.Request.Path.Value = "/" OrElse context.Request.Path.Value = "" Then
Dim indexPath = System.IO.Path.Combine(RootPath, "index.html")
If System.IO.File.Exists(indexPath) Then
context.Response.Redirect("/index.html")
Else
context.Response.StatusCode = 200
context.Response.ContentType = "text/html"
Dim tcs = New System.Threading.Tasks.TaskCompletionSource(Of Integer)()
context.Response.WriteAsync("<html><body><h1>ECO2 Web Server</h1><p>서버가 정상적으로 실행 중입니다.</p><p>루트 경로: " & RootPath & "</p></body></html>")
tcs.SetResult(0)
Return tcs.Task
End If
End If
Dim tcs2 = New System.Threading.Tasks.TaskCompletionSource(Of Integer)()
tcs2.SetResult(0)
Return tcs2.Task
End Function)
End Sub
End Class
''' <summary>
''' 커스텀 Content Type Provider
''' </summary>
Public Class CustomContentTypeProvider
Inherits Microsoft.Owin.StaticFiles.ContentTypes.FileExtensionContentTypeProvider
Public Sub New()
MyBase.New()
' 추가 MIME 타입 매핑 (필요한 경우)
' 기본적으로 일반적인 타입들은 이미 포함되어 있음
If Not Me.Mappings.ContainsKey(".json") Then
Me.Mappings.Add(".json", "application/json")
End If
If Not Me.Mappings.ContainsKey(".svg") Then
Me.Mappings.Add(".svg", "image/svg+xml")
End If
If Not Me.Mappings.ContainsKey(".woff") Then
Me.Mappings.Add(".woff", "font/woff")
End If
If Not Me.Mappings.ContainsKey(".woff2") Then
Me.Mappings.Add(".woff2", "font/woff2")
End If
End Sub
End Class
End Namespace

View File

@@ -1,175 +0,0 @@
' OWIN 기반 정적 파일 호스팅 서버
'
' 사용 방법:
' Dim server As New StaticFileServer("C:\wwwroot", 58123)
' server.Start()
' ... 프로그램 실행 ...
' server.Stop()
Imports System
Imports System.IO
Imports Microsoft.Owin.Hosting
Namespace WebServer
''' <summary>
''' OWIN 기반 정적 파일 호스팅 서버
''' 포트 58123 사용 (일반적으로 사용하지 않는 포트)
''' </summary>
Public Class StaticFileServer
Implements IDisposable
Private _webApp As IDisposable
Private _baseUrl As String
Private _rootPath As String
Private _isRunning As Boolean = False
''' <summary>
''' 서버가 실행 중인지 여부
''' </summary>
Public ReadOnly Property IsRunning As Boolean
Get
Return _isRunning
End Get
End Property
''' <summary>
''' 서버 URL (예: http://localhost:58123)
''' </summary>
Public ReadOnly Property BaseUrl As String
Get
Return _baseUrl
End Get
End Property
''' <summary>
''' 정적 파일 루트 경로
''' </summary>
Public ReadOnly Property RootPath As String
Get
Return _rootPath
End Get
End Property
''' <summary>
''' StaticFileServer 생성자
''' </summary>
''' <param name="rootPath">정적 파일을 서빙할 루트 디렉토리 경로</param>
''' <param name="port">사용할 포트 번호 (기본값: 58123)</param>
Public Sub New(rootPath As String, Optional port As Integer = 58123)
If String.IsNullOrEmpty(rootPath) Then
Throw New ArgumentException("rootPath는 비어있을 수 없습니다.", "rootPath")
End If
If Not Directory.Exists(rootPath) Then
Directory.CreateDirectory(rootPath)
End If
_rootPath = Path.GetFullPath(rootPath)
_baseUrl = String.Format("http://localhost:{0}", port)
End Sub
''' <summary>
''' 웹 서버 시작
''' </summary>
Public Sub Start()
If _isRunning Then
Throw New InvalidOperationException("서버가 이미 실행 중입니다.")
End If
Try
' OWIN 서버 시작
_webApp = WebApp.Start(Of Startup)(_baseUrl)
_isRunning = True
' 루트 경로를 Startup에서 접근할 수 있도록 설정
Startup.RootPath = _rootPath
Console.WriteLine("웹 서버 시작: {0}", _baseUrl)
Console.WriteLine("루트 경로: {0}", _rootPath)
Catch ex As Exception
_isRunning = False
Throw New Exception("웹 서버 시작 실패: " & ex.Message, ex)
End Try
End Sub
''' <summary>
''' 웹 서버 중지
''' </summary>
Public Sub [Stop]()
If Not _isRunning Then
Return
End If
Try
If _webApp IsNot Nothing Then
_webApp.Dispose()
_webApp = Nothing
End If
_isRunning = False
Console.WriteLine("웹 서버 중지됨")
Catch ex As Exception
Throw New Exception("웹 서버 중지 실패: " & ex.Message, ex)
End Try
End Sub
''' <summary>
''' 리소스 해제
''' </summary>
Public Sub Dispose() Implements IDisposable.Dispose
[Stop]()
End Sub
''' <summary>
''' 특정 파일의 전체 URL 반환
''' </summary>
''' <param name="relativePath">상대 경로 (예: "index.html" 또는 "images/logo.png")</param>
''' <returns>전체 URL</returns>
Public Function GetFileUrl(relativePath As String) As String
If String.IsNullOrEmpty(relativePath) Then
Return _baseUrl & "/"
End If
' 경로 정규화
Dim normalizedPath As String = relativePath.Replace("\", "/")
If Not normalizedPath.StartsWith("/") Then
normalizedPath = "/" & normalizedPath
End If
Return _baseUrl & normalizedPath
End Function
''' <summary>
''' 브라우저에서 루트 URL 열기
''' </summary>
Public Sub OpenInBrowser()
If Not _isRunning Then
Throw New InvalidOperationException("서버가 실행 중이 아닙니다.")
End If
Try
System.Diagnostics.Process.Start(_baseUrl)
Catch ex As Exception
Throw New Exception("브라우저 열기 실패: " & ex.Message, ex)
End Try
End Sub
''' <summary>
''' 특정 파일을 브라우저에서 열기
''' </summary>
''' <param name="relativePath">상대 경로</param>
Public Sub OpenFileInBrowser(relativePath As String)
If Not _isRunning Then
Throw New InvalidOperationException("서버가 실행 중이 아닙니다.")
End If
Try
Dim url As String = GetFileUrl(relativePath)
System.Diagnostics.Process.Start(url)
Catch ex As Exception
Throw New Exception("브라우저 열기 실패: " & ex.Message, ex)
End Try
End Sub
End Class
End Namespace

View File

@@ -1,9 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net40" />
<package id="Microsoft.Owin.Host.HttpListener" version="2.1.0" targetFramework="net40" />
<package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net40" />
<package id="Microsoft.Owin.StaticFiles" version="2.1.0" targetFramework="net40" />
<package id="Microsoft.Web.WebView2" version="1.0.3537.50" targetFramework="net48" /> <package id="Microsoft.Web.WebView2" version="1.0.3537.50" targetFramework="net48" />
<package id="Owin" version="1.0" targetFramework="net40" />
</packages> </packages>